[PATCH rtems-libbsd 3/7] sys/kern: Add lockmgr support

Chris Johns chrisj at rtems.org
Wed Jul 28 23:05:11 UTC 2021


On 29/7/21 12:03 am, Gedare Bloom wrote:
> On Tue, Jul 27, 2021 at 2:59 AM <chrisj at rtems.org> wrote:
>> From: Chris Johns <chrisj at rtems.org>
>>
>>  struct lock_object {
>> -#ifndef __rtems__
>>         const   char *lo_name;          /* Individual lock name. */
>>         u_int   lo_flags;
>>         u_int   lo_data;                /* General class specific data. */
>> +#ifndef __rtems__
>>         struct  witness *lo_witness;    /* Data for witness. */
>> -#else /* __rtems__ */
>> -       unsigned int lo_flags;
>> +#endif /* __rtems__ */
>> +#ifdef __rtems__
> Can use
> #else /* __rtems__ */
> instead of endif+ifdef

I will see how this ends up after looking at the fields Sebastian wants removed.

>> +static void
>> +lock_lockmgr(struct lock_object *lock, uintptr_t how)
>> +{
>> +  panic("lockmgr locks do not support sleep interlocking");
>> +}
>> +
>> +static uintptr_t
>> +unlock_lockmgr(struct lock_object *lock)
>> +{
>> +  panic("lockmgr locks do not support sleep interlocking");
>> +}
>> +
> Should there be different messages for the two cases here?

Sure. Either case means something is being used by new ported code and these
calls need to be looked into.

> 
>> +static struct thread *
>> +lockmgr_xholder(const struct lock *lk)
>> +{
>> +  uintptr_t x;
>> +  x = lk->lk_lock;
>> +  if ((x & LK_SHARE))
>> +    return NULL;
>> +  return rtems_bsd_get_thread(lk->lock_object.lo_mtx.queue.Queue.owner);
>> +}
>> +
>> +static void
>> +lockmgr_exit(u_int flags, struct lock_object *ilk, int wakeup_swapper)
> any good reason to use ilk instead of lk as elsewhere?

None. I copy the decl from FreeBSD ...

freebsd/sys/kern/kern_lock.c:lockmgr_exit(u_int flags, struct lock_object *ilk,
int wakeup_swapper)

>> +static int
>> +lockmgr_slock_hard(struct lock *lk, u_int flags, struct lock_object *ilk,
>> +                  const char *file, int line)
>> +{
>> +  uintptr_t x;
>> +  int error = 0;
>> +  lockmgr_trace("slock", 'I', lk);
>> +  rtems_bsd_mutex_lock(&lk->lock_object);
>> +  x = lk->lk_lock;
>> +  atomic_store_rel_ptr(&lk->lk_lock, x + LK_ONE_SHARER);
>> +  if (rtems_bsd_mutex_recursed(&lk->lock_object))
>> +    lk->lk_recurse++;
>> +  else
>> +    lk->lk_recurse = 0;
>> +  lockmgr_trace("slock", 'O', lk);
>> +  LOCK_LOG_LOCK("SLOCK", &lk->lock_object, 0, lk->lk_recurse, file, line);
>> +  lockmgr_exit(flags, ilk, 0);
>> +  return error;
> this is always 0 (successful)?

Yeap.

>> +static int
>> +lockmgr_upgrade(struct lock *lk, u_int flags, struct lock_object *ilk,
>> +               const char *file, int line)
>> +{
>> +  uintptr_t x, v;
>> +  int error = 0;
>> +  LOCK_LOG_LOCK("XUPGRADE", &lk->lock_object, 0, 0, file, line);
>> +  lockmgr_trace("xupgrade", 'I', lk);
>> +  v = lk->lk_lock;
>> +  x = v & ~LK_SHARE;
>> +  atomic_store_rel_ptr(&lk->lk_lock, x);
> 
> I think this function is to upgrade a shared (waiters/spinner) lock to
> non-shared (spinner) lock? I'm not confident about correctness here.
> It looks to me like there can be a race condition if multiple waiters
> attempt to upgrade in parallel. It works by a preemption after the
> first waiter loads `v = lk->lk_lock` and then another waiter loads
> `v`. Actually, there doesn't seem to be anything that prevents two
> separate calls to upgrade the lock by different waiters in sequence
> either. I could be wrong (of course).

We do not support shared locks and we do not share specific paths through locks
so while the code may request a shared lock it is not shared.

You could be correct and I welcome you reviewing the code in the FB kernel this
is based on.

>> +int
>> +lockstatus(const struct lock *lk)
>> +{
>> +  uintptr_t v, x;
>> +  int ret;
>> +
>> +  ret = LK_SHARED;
>> +  x = lk->lk_lock;
>> +
>> +  if ((x & LK_SHARE) == 0) {
>> +    v = rtems_bsd_mutex_owned(RTEMS_DECONST(struct lock_object*, &lk->lock_object));
>> +    if (v)
>> +      ret = LK_EXCLUSIVE;
>> +    else
>> +      ret = LK_EXCLOTHER;
>> +  } else if (x == LK_UNLOCKED) {
>> +    ret = 0;
>> +  }
> 
> there's no else {} here, is it possible that (x & LK_SHARE) != 0, and
> (x != LK_UNLOCKED)? If so, ret may be returned without initialization?
> 
> Maybe just initialize ret = 0.

Yes and thanks.

Chris



More information about the devel mailing list