Hi,

After this commit, the kernel stalls just before root file system
will be found on my NetBSD/amd64 laptop.

Reverting
src/sys/kern/kern_rwlock.c to r1.60
and
src/sys/sys/rwlock.h to r1.12
in latest -current tree and I can get the kernel that works like
before.

And on another laptop, the problematic kernel stalls before root file
system detection like my laptop.

It may be universal problem.

Could you take a look at this problem?

Thank you.

"Andrew Doran" <a...@netbsd.org> writes:

> Module Name:  src
> Committed By: ad
> Date:         Sun Jan 19 18:34:24 UTC 2020
>
> Modified Files:
>       src/sys/kern: kern_rwlock.c
>       src/sys/sys: rwlock.h
>
> Log Message:
> Tidy rwlocks a bit, no functional change intended.  Mainly:
>
> - rw_downgrade(): do it in a for () loop like all the others.
> - Explicitly carry around RW_NODEBUG - don't be lazy.
> - Remove pointless macros.
> - Don't make assertions conditional on LOCKDEBUG, there's no reason.
> - Make space for a new flag bit (not added yet).
>
>
> To generate a diff of this commit:
> cvs rdiff -u -r1.60 -r1.61 src/sys/kern/kern_rwlock.c
> cvs rdiff -u -r1.12 -r1.13 src/sys/sys/rwlock.h
>
> Please note that diffs are not public domain; they are subject to the
> copyright notices on the relevant files.
>
> Modified files:
>
> Index: src/sys/kern/kern_rwlock.c
> diff -u src/sys/kern/kern_rwlock.c:1.60 src/sys/kern/kern_rwlock.c:1.61
> --- src/sys/kern/kern_rwlock.c:1.60   Sun Jan 12 18:37:10 2020
> +++ src/sys/kern/kern_rwlock.c        Sun Jan 19 18:34:24 2020
> @@ -1,4 +1,4 @@
> -/*   $NetBSD: kern_rwlock.c,v 1.60 2020/01/12 18:37:10 ad Exp $      */
> +/*   $NetBSD: kern_rwlock.c,v 1.61 2020/01/19 18:34:24 ad Exp $      */
>  
>  /*-
>   * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2019, 2020
> @@ -39,7 +39,9 @@
>   */
>  
>  #include <sys/cdefs.h>
> -__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.60 2020/01/12 18:37:10 ad Exp 
> $");
> +__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.61 2020/01/19 18:34:24 ad Exp 
> $");
> +
> +#include "opt_lockdebug.h"
>  
>  #define      __RWLOCK_PRIVATE
>  
> @@ -63,58 +65,32 @@ __KERNEL_RCSID(0, "$NetBSD: kern_rwlock.
>   * LOCKDEBUG
>   */
>  
> -#if defined(LOCKDEBUG)
> -
> -#define      RW_WANTLOCK(rw, op)                                             
> \
> -     LOCKDEBUG_WANTLOCK(RW_DEBUG_P(rw), (rw),                        \
> -         (uintptr_t)__builtin_return_address(0), op == RW_READER);
> -#define      RW_LOCKED(rw, op)                                               
> \
> -     LOCKDEBUG_LOCKED(RW_DEBUG_P(rw), (rw), NULL,                    \
> -         (uintptr_t)__builtin_return_address(0), op == RW_READER);
> -#define      RW_UNLOCKED(rw, op)                                             
> \
> -     LOCKDEBUG_UNLOCKED(RW_DEBUG_P(rw), (rw),                        \
> -         (uintptr_t)__builtin_return_address(0), op == RW_READER);
> -#define      RW_DASSERT(rw, cond)                                            
> \
> -do {                                                                 \
> -     if (__predict_false(!(cond)))                                   \
> -             rw_abort(__func__, __LINE__, rw, "assertion failed: " #cond);\
> -} while (/* CONSTCOND */ 0);
> -
> -#else        /* LOCKDEBUG */
> -
> -#define      RW_WANTLOCK(rw, op)     /* nothing */
> -#define      RW_LOCKED(rw, op)       /* nothing */
> -#define      RW_UNLOCKED(rw, op)     /* nothing */
> -#define      RW_DASSERT(rw, cond)    /* nothing */
> +#define      RW_DEBUG_P(rw)          (((rw)->rw_owner & RW_NODEBUG) == 0)
>  
> -#endif       /* LOCKDEBUG */
> +#define      RW_WANTLOCK(rw, op) \
> +    LOCKDEBUG_WANTLOCK(RW_DEBUG_P(rw), (rw), \
> +        (uintptr_t)__builtin_return_address(0), op == RW_READER);
> +#define      RW_LOCKED(rw, op) \
> +    LOCKDEBUG_LOCKED(RW_DEBUG_P(rw), (rw), NULL, \
> +        (uintptr_t)__builtin_return_address(0), op == RW_READER);
> +#define      RW_UNLOCKED(rw, op) \
> +    LOCKDEBUG_UNLOCKED(RW_DEBUG_P(rw), (rw), \
> +        (uintptr_t)__builtin_return_address(0), op == RW_READER);
>  
>  /*
>   * DIAGNOSTIC
>   */
>  
>  #if defined(DIAGNOSTIC)
> -
> -#define      RW_ASSERT(rw, cond)                                             
> \
> -do {                                                                 \
> -     if (__predict_false(!(cond)))                                   \
> +#define      RW_ASSERT(rw, cond) \
> +do { \
> +     if (__predict_false(!(cond))) \
>               rw_abort(__func__, __LINE__, rw, "assertion failed: " #cond);\
>  } while (/* CONSTCOND */ 0)
> -
>  #else
> -
>  #define      RW_ASSERT(rw, cond)     /* nothing */
> -
>  #endif       /* DIAGNOSTIC */
>  
> -#define      RW_SETDEBUG(rw, on)             ((rw)->rw_owner |= (on) ? 0 : 
> RW_NODEBUG)
> -#define      RW_DEBUG_P(rw)                  (((rw)->rw_owner & RW_NODEBUG) 
> == 0)
> -#if defined(LOCKDEBUG)
> -#define      RW_INHERITDEBUG(n, o)           (n) |= (o) & RW_NODEBUG
> -#else /* defined(LOCKDEBUG) */
> -#define      RW_INHERITDEBUG(n, o)           /* nothing */
> -#endif /* defined(LOCKDEBUG) */
> -
>  /*
>   * Memory barriers.
>   */
> @@ -128,29 +104,6 @@ do {                                                     
>                 \
>  #define      RW_MEMBAR_PRODUCER()            membar_producer()
>  #endif
>  
> -static void  rw_abort(const char *, size_t, krwlock_t *, const char *);
> -static void  rw_dump(const volatile void *, lockop_printer_t);
> -static lwp_t *rw_owner(wchan_t);
> -
> -static inline uintptr_t
> -rw_cas(krwlock_t *rw, uintptr_t o, uintptr_t n)
> -{
> -
> -     RW_INHERITDEBUG(n, o);
> -     return (uintptr_t)atomic_cas_ptr((volatile void *)&rw->rw_owner,
> -         (void *)o, (void *)n);
> -}
> -
> -static inline void
> -rw_swap(krwlock_t *rw, uintptr_t o, uintptr_t n)
> -{
> -
> -     RW_INHERITDEBUG(n, o);
> -     n = (uintptr_t)atomic_swap_ptr((volatile void *)&rw->rw_owner,
> -         (void *)n);
> -     RW_DASSERT(rw, n == o);
> -}
> -
>  /*
>   * For platforms that do not provide stubs, or for the LOCKDEBUG case.
>   */
> @@ -164,6 +117,10 @@ __strong_alias(rw_exit,rw_vector_exit);
>  __strong_alias(rw_tryenter,rw_vector_tryenter);
>  #endif
>  
> +static void  rw_abort(const char *, size_t, krwlock_t *, const char *);
> +static void  rw_dump(const volatile void *, lockop_printer_t);
> +static lwp_t *rw_owner(wchan_t);
> +
>  lockops_t rwlock_lockops = {
>       .lo_name = "Reader / writer lock",
>       .lo_type = LOCKOPS_SLEEP,
> @@ -179,6 +136,37 @@ syncobj_t rw_syncobj = {
>  };
>  
>  /*
> + * rw_cas:
> + *
> + *   Do an atomic compare-and-swap on the lock word.
> + */
> +static inline uintptr_t
> +rw_cas(krwlock_t *rw, uintptr_t o, uintptr_t n)
> +{
> +
> +     return (uintptr_t)atomic_cas_ptr((volatile void *)&rw->rw_owner,
> +         (void *)o, (void *)n);
> +}
> +
> +/*
> + * rw_swap:
> + *
> + *   Do an atomic swap of the lock word.  This is used only when it's
> + *   known that the lock word is set up such that it can't be changed
> + *   behind us (assert this), so there's no point considering the result.
> + */
> +static inline void
> +rw_swap(krwlock_t *rw, uintptr_t o, uintptr_t n)
> +{
> +
> +     n = (uintptr_t)atomic_swap_ptr((volatile void *)&rw->rw_owner,
> +         (void *)n);
> +
> +     RW_ASSERT(rw, n == o);
> +     RW_ASSERT(rw, (o & RW_HAS_WAITERS) != 0);
> +}
> +
> +/*
>   * rw_dump:
>   *
>   *   Dump the contents of a rwlock structure.
> @@ -214,16 +202,14 @@ rw_abort(const char *func, size_t line, 
>   *
>   *   Initialize a rwlock for use.
>   */
> -void _rw_init(krwlock_t *, uintptr_t);
>  void
>  _rw_init(krwlock_t *rw, uintptr_t return_address)
>  {
> -     bool dodebug;
>  
> -     memset(rw, 0, sizeof(*rw));
> -
> -     dodebug = LOCKDEBUG_ALLOC(rw, &rwlock_lockops, return_address);
> -     RW_SETDEBUG(rw, dodebug);
> +     if (LOCKDEBUG_ALLOC(rw, &rwlock_lockops, return_address))
> +             rw->rw_owner = 0;
> +     else
> +             rw->rw_owner = RW_NODEBUG;
>  }
>  
>  void
> @@ -243,7 +229,7 @@ rw_destroy(krwlock_t *rw)
>  {
>  
>       RW_ASSERT(rw, (rw->rw_owner & ~RW_NODEBUG) == 0);
> -     LOCKDEBUG_FREE(RW_DEBUG_P(rw), rw);
> +     LOCKDEBUG_FREE((rw->rw_owner & RW_NODEBUG) == 0, rw);
>  }
>  
>  /*
> @@ -327,7 +313,7 @@ rw_vector_enter(krwlock_t *rw, const krw
>               need_wait = RW_WRITE_LOCKED | RW_WRITE_WANTED;
>               queue = TS_READER_Q;
>       } else {
> -             RW_DASSERT(rw, op == RW_WRITER);
> +             RW_ASSERT(rw, op == RW_WRITER);
>               incr = curthread | RW_WRITE_LOCKED;
>               set_wait = RW_HAS_WAITERS | RW_WRITE_WANTED;
>               need_wait = RW_WRITE_LOCKED | RW_THREAD;
> @@ -430,7 +416,7 @@ rw_vector_enter(krwlock_t *rw, const krw
>             (uintptr_t)__builtin_return_address(0)));
>       LOCKSTAT_EXIT(lsflag);
>  
> -     RW_DASSERT(rw, (op != RW_READER && RW_OWNER(rw) == curthread) ||
> +     RW_ASSERT(rw, (op != RW_READER && RW_OWNER(rw) == curthread) ||
>           (op == RW_READER && RW_COUNT(rw) != 0));
>       RW_LOCKED(rw, op);
>  }
> @@ -448,7 +434,8 @@ rw_vector_exit(krwlock_t *rw)
>       int rcnt, wcnt;
>       lwp_t *l;
>  
> -     curthread = (uintptr_t)curlwp;
> +     l = curlwp;
> +     curthread = (uintptr_t)l;
>       RW_ASSERT(rw, curthread != 0);
>  
>       /*
> @@ -491,8 +478,8 @@ rw_vector_exit(krwlock_t *rw)
>        */
>       ts = turnstile_lookup(rw);
>       owner = rw->rw_owner;
> -     RW_DASSERT(rw, ts != NULL);
> -     RW_DASSERT(rw, (owner & RW_HAS_WAITERS) != 0);
> +     RW_ASSERT(rw, ts != NULL);
> +     RW_ASSERT(rw, (owner & RW_HAS_WAITERS) != 0);
>  
>       wcnt = TS_WAITERS(ts, TS_WRITER_Q);
>       rcnt = TS_WAITERS(ts, TS_READER_Q);
> @@ -509,31 +496,35 @@ rw_vector_exit(krwlock_t *rw)
>        * do the work of acquiring the lock in rw_vector_enter().
>        */
>       if (rcnt == 0 || decr == RW_READ_INCR) {
> -             RW_DASSERT(rw, wcnt != 0);
> -             RW_DASSERT(rw, (owner & RW_WRITE_WANTED) != 0);
> +             RW_ASSERT(rw, wcnt != 0);
> +             RW_ASSERT(rw, (owner & RW_WRITE_WANTED) != 0);
>  
>               if (rcnt != 0) {
>                       /* Give the lock to the longest waiting writer. */
>                       l = TS_FIRST(ts, TS_WRITER_Q);
> -                     newown = (uintptr_t)l | RW_WRITE_LOCKED | 
> RW_HAS_WAITERS;
> +                     newown = (uintptr_t)l | (owner & RW_NODEBUG);
> +                     newown |= RW_WRITE_LOCKED | RW_HAS_WAITERS;
>                       if (wcnt > 1)
>                               newown |= RW_WRITE_WANTED;
>                       rw_swap(rw, owner, newown);
>                       turnstile_wakeup(ts, TS_WRITER_Q, 1, l);
>               } else {
>                       /* Wake all writers and let them fight it out. */
> -                     rw_swap(rw, owner, RW_WRITE_WANTED);
> +                     newown = owner & RW_NODEBUG;
> +                     newown |= RW_WRITE_WANTED;
> +                     rw_swap(rw, owner, newown);
>                       turnstile_wakeup(ts, TS_WRITER_Q, wcnt, NULL);
>               }
>       } else {
> -             RW_DASSERT(rw, rcnt != 0);
> +             RW_ASSERT(rw, rcnt != 0);
>  
>               /*
>                * Give the lock to all blocked readers.  If there
>                * is a writer waiting, new readers that arrive
>                * after the release will be blocked out.
>                */
> -             newown = rcnt << RW_READ_COUNT_SHIFT;
> +             newown = owner & RW_NODEBUG;
> +             newown += rcnt << RW_READ_COUNT_SHIFT;
>               if (wcnt != 0)
>                       newown |= RW_HAS_WAITERS | RW_WRITE_WANTED;
>                       
> @@ -552,8 +543,10 @@ int
>  rw_vector_tryenter(krwlock_t *rw, const krw_t op)
>  {
>       uintptr_t curthread, owner, incr, need_wait, next;
> +     lwp_t *l;
>  
> -     curthread = (uintptr_t)curlwp;
> +     l = curlwp;
> +     curthread = (uintptr_t)l;
>  
>       RW_ASSERT(rw, curthread != 0);
>  
> @@ -561,7 +554,7 @@ rw_vector_tryenter(krwlock_t *rw, const 
>               incr = RW_READ_INCR;
>               need_wait = RW_WRITE_LOCKED | RW_WRITE_WANTED;
>       } else {
> -             RW_DASSERT(rw, op == RW_WRITER);
> +             RW_ASSERT(rw, op == RW_WRITER);
>               incr = curthread | RW_WRITE_LOCKED;
>               need_wait = RW_WRITE_LOCKED | RW_THREAD;
>       }
> @@ -572,24 +565,23 @@ rw_vector_tryenter(krwlock_t *rw, const 
>               next = rw_cas(rw, owner, owner + incr);
>               if (__predict_true(next == owner)) {
>                       /* Got it! */
> -                     RW_MEMBAR_ENTER();
>                       break;
>               }
>       }
>  
>       RW_WANTLOCK(rw, op);
>       RW_LOCKED(rw, op);
> -     RW_DASSERT(rw, (op != RW_READER && RW_OWNER(rw) == curthread) ||
> +     RW_ASSERT(rw, (op != RW_READER && RW_OWNER(rw) == curthread) ||
>           (op == RW_READER && RW_COUNT(rw) != 0));
>  
> +     RW_MEMBAR_ENTER();
>       return 1;
>  }
>  
>  /*
>   * rw_downgrade:
>   *
> - *   Downgrade a write lock to a read lock.  Optimise memory accesses for
> - *   the uncontended case.
> + *   Downgrade a write lock to a read lock.
>   */
>  void
>  rw_downgrade(krwlock_t *rw)
> @@ -597,55 +589,64 @@ rw_downgrade(krwlock_t *rw)
>       uintptr_t owner, curthread, newown, next;
>       turnstile_t *ts;
>       int rcnt, wcnt;
> +     lwp_t *l;
>  
> -     curthread = (uintptr_t)curlwp;
> +     l = curlwp;
> +     curthread = (uintptr_t)l;
>       RW_ASSERT(rw, curthread != 0);
> -     RW_DASSERT(rw, (rw->rw_owner & RW_WRITE_LOCKED) != 0);
> +     RW_ASSERT(rw, (rw->rw_owner & RW_WRITE_LOCKED) != 0);
>       RW_ASSERT(rw, RW_OWNER(rw) == curthread);
>       RW_UNLOCKED(rw, RW_WRITER);
>  #if !defined(DIAGNOSTIC)
>       __USE(curthread);
>  #endif
>  
> -     /*
> -      * If there are no waiters, so we can do this the easy way.
> -      * Try swapping us down to one read hold.  If it fails, the
> -      * lock condition has changed and we most likely now have
> -      * waiters.
> -      */
>       RW_MEMBAR_PRODUCER();
> -     owner = curthread | RW_WRITE_LOCKED;
> -     next = rw_cas(rw, owner, RW_READ_INCR);
> -     if (__predict_true(next == owner)) {
> -             RW_LOCKED(rw, RW_READER);
> -             RW_DASSERT(rw, (rw->rw_owner & RW_WRITE_LOCKED) == 0);
> -             RW_DASSERT(rw, RW_COUNT(rw) != 0);
> -             return;
> -     }
>  
> -     /*
> -      * Grab the turnstile chain lock.  This gets the interlock
> -      * on the sleep queue.  Once we have that, we can adjust the
> -      * waiter bits.
> -      */
> -     for (;;) {
> -             owner = next;
> +     for (owner = rw->rw_owner;; owner = next) {
> +             /*
> +              * If there are no waiters we can do this the easy way.  Try
> +              * swapping us down to one read hold.  If it fails, the lock
> +              * condition has changed and we most likely now have
> +              * waiters.
> +              */
> +             if ((owner & RW_HAS_WAITERS) == 0) {
> +                     newown = (owner & RW_NODEBUG);
> +                     next = rw_cas(rw, owner, newown + RW_READ_INCR);
> +                     if (__predict_true(next == owner)) {
> +                             RW_LOCKED(rw, RW_READER);
> +                             RW_ASSERT(rw,
> +                                 (rw->rw_owner & RW_WRITE_LOCKED) == 0);
> +                             RW_ASSERT(rw, RW_COUNT(rw) != 0);
> +                             return;
> +                     }
> +                     continue;
> +             }
> +
> +             /*
> +              * Grab the turnstile chain lock.  This gets the interlock
> +              * on the sleep queue.  Once we have that, we can adjust the
> +              * waiter bits.
> +              */
>               ts = turnstile_lookup(rw);
> -             RW_DASSERT(rw, ts != NULL);
> +             RW_ASSERT(rw, ts != NULL);
>  
>               rcnt = TS_WAITERS(ts, TS_READER_Q);
>               wcnt = TS_WAITERS(ts, TS_WRITER_Q);
>  
> -             /*
> -              * If there are no readers, just preserve the waiters
> -              * bits, swap us down to one read hold and return.
> -              */
>               if (rcnt == 0) {
> -                     RW_DASSERT(rw, wcnt != 0);
> -                     RW_DASSERT(rw, (rw->rw_owner & RW_WRITE_WANTED) != 0);
> -                     RW_DASSERT(rw, (rw->rw_owner & RW_HAS_WAITERS) != 0);
> -
> -                     newown = RW_READ_INCR | RW_HAS_WAITERS | 
> RW_WRITE_WANTED;
> +                     /*
> +                      * If there are no readers, just preserve the
> +                      * waiters bits, swap us down to one read hold and
> +                      * return.
> +                      */
> +                     RW_ASSERT(rw, wcnt != 0);
> +                     RW_ASSERT(rw, (rw->rw_owner & RW_WRITE_WANTED) != 0);
> +                     RW_ASSERT(rw, (rw->rw_owner & RW_HAS_WAITERS) != 0);
> +
> +                     newown = owner & RW_NODEBUG;
> +                     newown = RW_READ_INCR | RW_HAS_WAITERS |
> +                         RW_WRITE_WANTED;
>                       next = rw_cas(rw, owner, newown);
>                       turnstile_exit(rw);
>                       if (__predict_true(next == owner))
> @@ -653,11 +654,12 @@ rw_downgrade(krwlock_t *rw)
>               } else {
>                       /*
>                        * Give the lock to all blocked readers.  We may
> -                      * retain one read hold if downgrading.  If there
> -                      * is a writer waiting, new readers will be blocked
> +                      * retain one read hold if downgrading.  If there is
> +                      * a writer waiting, new readers will be blocked
>                        * out.
>                        */
> -                     newown = (rcnt << RW_READ_COUNT_SHIFT) + RW_READ_INCR;
> +                     newown = owner & RW_NODEBUG;
> +                     newown += (rcnt << RW_READ_COUNT_SHIFT) + RW_READ_INCR;
>                       if (wcnt != 0)
>                               newown |= RW_HAS_WAITERS | RW_WRITE_WANTED;
>  
> @@ -673,22 +675,24 @@ rw_downgrade(krwlock_t *rw)
>  
>       RW_WANTLOCK(rw, RW_READER);
>       RW_LOCKED(rw, RW_READER);
> -     RW_DASSERT(rw, (rw->rw_owner & RW_WRITE_LOCKED) == 0);
> -     RW_DASSERT(rw, RW_COUNT(rw) != 0);
> +     RW_ASSERT(rw, (rw->rw_owner & RW_WRITE_LOCKED) == 0);
> +     RW_ASSERT(rw, RW_COUNT(rw) != 0);
>  }
>  
>  /*
>   * rw_tryupgrade:
>   *
>   *   Try to upgrade a read lock to a write lock.  We must be the only
> - *   reader.  Optimise memory accesses for the uncontended case.
> + *   reader.
>   */
>  int
>  rw_tryupgrade(krwlock_t *rw)
>  {
>       uintptr_t owner, curthread, newown, next;
> +     struct lwp *l;
>  
> -     curthread = (uintptr_t)curlwp;
> +     l = curlwp;
> +     curthread = (uintptr_t)l;
>       RW_ASSERT(rw, curthread != 0);
>       RW_ASSERT(rw, rw_read_held(rw));
>  
> @@ -709,8 +713,8 @@ rw_tryupgrade(krwlock_t *rw)
>       RW_UNLOCKED(rw, RW_READER);
>       RW_WANTLOCK(rw, RW_WRITER);
>       RW_LOCKED(rw, RW_WRITER);
> -     RW_DASSERT(rw, rw->rw_owner & RW_WRITE_LOCKED);
> -     RW_DASSERT(rw, RW_OWNER(rw) == curthread);
> +     RW_ASSERT(rw, rw->rw_owner & RW_WRITE_LOCKED);
> +     RW_ASSERT(rw, RW_OWNER(rw) == curthread);
>  
>       return 1;
>  }
>
> Index: src/sys/sys/rwlock.h
> diff -u src/sys/sys/rwlock.h:1.12 src/sys/sys/rwlock.h:1.13
> --- src/sys/sys/rwlock.h:1.12 Wed Jan  1 21:34:39 2020
> +++ src/sys/sys/rwlock.h      Sun Jan 19 18:34:24 2020
> @@ -1,7 +1,7 @@
> -/*   $NetBSD: rwlock.h,v 1.12 2020/01/01 21:34:39 ad Exp $   */
> +/*   $NetBSD: rwlock.h,v 1.13 2020/01/19 18:34:24 ad Exp $   */
>  
>  /*-
> - * Copyright (c) 2002, 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc.
> + * Copyright (c) 2002, 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, 
> Inc.
>   * All rights reserved.
>   *
>   * This code is derived from software contributed to The NetBSD Foundation
> @@ -45,10 +45,6 @@
>   *   rw_tryenter()
>   */
>  
> -#if defined(_KERNEL_OPT)
> -#include "opt_lockdebug.h"
> -#endif
> -
>  #if !defined(_KERNEL)
>  #include <sys/types.h>
>  #include <sys/inttypes.h>
> @@ -75,13 +71,9 @@ typedef struct krwlock krwlock_t;
>  #define      RW_HAS_WAITERS          0x01UL  /* lock has waiters */
>  #define      RW_WRITE_WANTED         0x02UL  /* >= 1 waiter is a writer */
>  #define      RW_WRITE_LOCKED         0x04UL  /* lock is currently write 
> locked */
> -#if defined(LOCKDEBUG)
> -#define      RW_NODEBUG              0x08UL  /* LOCKDEBUG disabled */
> -#else
> -#define      RW_NODEBUG              0x00UL  /* do nothing */
> -#endif       /* LOCKDEBUG */
> +#define      RW_NODEBUG              0x10UL  /* LOCKDEBUG disabled */
>  
> -#define      RW_READ_COUNT_SHIFT     4
> +#define      RW_READ_COUNT_SHIFT     5
>  #define      RW_READ_INCR            (1UL << RW_READ_COUNT_SHIFT)
>  #define      RW_THREAD               ((uintptr_t)-RW_READ_INCR)
>  #define      RW_OWNER(rw)            ((rw)->rw_owner & RW_THREAD)
> @@ -91,6 +83,7 @@ typedef struct krwlock krwlock_t;
>  void rw_vector_enter(krwlock_t *, const krw_t);
>  void rw_vector_exit(krwlock_t *);
>  int  rw_vector_tryenter(krwlock_t *, const krw_t);
> +void _rw_init(krwlock_t *, uintptr_t);
>  #endif       /* __RWLOCK_PRIVATE */
>  
>  struct krwlock {
>

-- 
Ryo ONODERA // r...@tetera.org
PGP fingerprint = 82A2 DC91 76E0 A10A 8ABB  FD1B F404 27FA C7D1 15F3

Reply via email to