Hi,

This diff introduces rrwlocks or recursive/re-entrant rwlocks. They are
needed due to the locking must be done in the VFS layer.

This diff also removes lockmgr() as the only user of it are the vnode
locks, as it was the only locking primitive we had that supported
recursion.

I'd love to hear test reports from people, using this diff and playing
with there media (msdos/ext2fs/udf/cd9660/mfs/ufs).

ciao, thib.

diff --git a/kern/kern_lock.c b/kern/kern_lock.c
index 320d2f3..97fdbda 100644
--- a/kern/kern_lock.c
+++ b/kern/kern_lock.c
@@ -43,299 +43,60 @@
 
 #include <machine/cpu.h>
 
-/*
- * Locking primitives implementation.
- * Locks provide shared/exclusive synchronization.
- */
-
-/*
- * Acquire a resource.
- */
-#define ACQUIRE(lkp, error, extflags, drain, wanted)                   \
-do {                                                                   \
-       for (error = 0; wanted; ) {                                     \
-               if ((drain))                                            \
-                       (lkp)->lk_flags |= LK_WAITDRAIN;                \
-               else                                                    \
-                       (lkp)->lk_waitcount++;                          \
-               /* XXX Cast away volatile. */                           \
-               error = tsleep((drain) ?                                \
-                   (void *)&(lkp)->lk_flags : (void *)(lkp),           \
-                   (lkp)->lk_prio, (lkp)->lk_wmesg, (lkp)->lk_timo);   \
-               if ((drain) == 0)                                       \
-                       (lkp)->lk_waitcount--;                          \
-               if (error)                                              \
-                       break;                                          \
-       }                                                               \
-} while (0)
-
-#define        SETHOLDER(lkp, pid, cpu_id)                                     
\
-       (lkp)->lk_lockholder = (pid)
+#ifdef MP_LOCKDEBUG
+/* CPU-dependent timing, needs this to be settable from ddb. */
+int __mp_lock_spinout = 200000000;
+#endif
 
-#define        WEHOLDIT(lkp, pid, cpu_id)                                      
\
-       ((lkp)->lk_lockholder == (pid))
 
-/*
- * Initialize a lock; required before use.
- */
 void
 lockinit(struct lock *lkp, int prio, char *wmesg, int timo, int flags)
 {
 
+       KASSERT(flags == 0);
+
        bzero(lkp, sizeof(struct lock));
-       lkp->lk_flags = flags & LK_EXTFLG_MASK;
-       lkp->lk_lockholder = LK_NOPROC;
-       lkp->lk_prio = prio;
-       lkp->lk_timo = timo;
-       lkp->lk_wmesg = wmesg;  /* just a name for spin locks */
+       rrw_init(&lkp->lk_lck, wmesg);
 }
 
-/*
- * Determine the status of a lock.
- */
 int
 lockstatus(struct lock *lkp)
 {
-       int lock_type = 0;
-
-       if (lkp->lk_exclusivecount != 0)
-               lock_type = LK_EXCLUSIVE;
-       else if (lkp->lk_sharecount != 0)
-               lock_type = LK_SHARED;
-       return (lock_type);
+       return (rrw_status(&lkp->lk_lck));
 }
 
-/*
- * Set, change, or release a lock.
- *
- * Shared requests increment the shared count. Exclusive requests set the
- * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
- * accepted shared locks and shared-to-exclusive upgrades to go away.
- */
 int
-lockmgr(__volatile struct lock *lkp, u_int flags, void *notused)
+lockmgr(struct lock *lkp, u_int flags, void *notused)
 {
-       int error;
-       pid_t pid;
-       int extflags;
-       cpuid_t cpu_id;
-       struct proc *p = curproc;
+       int     rwflags;
 
-       error = 0;
-       extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
+       rwflags = 0;
 
-#ifdef DIAGNOSTIC
-       if (p == NULL)
-               panic("lockmgr: process context required");
-#endif         
-       /* Process context required. */
-       pid = p->p_pid;
-       cpu_id = cpu_number();
-
-       /*
-        * Once a lock has drained, the LK_DRAINING flag is set and an
-        * exclusive lock is returned. The only valid operation thereafter
-        * is a single release of that exclusive lock. This final release
-        * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
-        * further requests of any sort will result in a panic. The bits
-        * selected for these two flags are chosen so that they will be set
-        * in memory that is freed (freed memory is filled with 0xdeadbeef).
-        */
-       if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
-#ifdef DIAGNOSTIC
-               if (lkp->lk_flags & LK_DRAINED)
-                       panic("lockmgr: using decommissioned lock");
-               if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
-                   WEHOLDIT(lkp, pid, cpu_id) == 0)
-                       panic("lockmgr: non-release on draining lock: %d",
-                           flags & LK_TYPE_MASK);
-#endif /* DIAGNOSTIC */
-               lkp->lk_flags &= ~LK_DRAINING;
-               lkp->lk_flags |= LK_DRAINED;
-       }
+       KASSERT(!((flags & (LK_SHARED|LK_EXCLUSIVE)) ==
+           (LK_SHARED|LK_EXCLUSIVE)));
+       KASSERT(!((flags & (LK_CANRECURSE|LK_RECURSEFAIL)) ==
+           (LK_CANRECURSE|LK_RECURSEFAIL)));
+       KASSERT((flags & LK_RELEASE) ||
+           (flags & (LK_SHARED|LK_EXCLUSIVE|LK_DRAIN)));
 
-       /*
-        * Check if the caller is asking us to be schizophrenic.
-        */
-       if ((lkp->lk_flags & (LK_CANRECURSE|LK_RECURSEFAIL)) ==
-           (LK_CANRECURSE|LK_RECURSEFAIL))
-               panic("lockmgr: make up your mind");
 
-       switch (flags & LK_TYPE_MASK) {
-
-       case LK_SHARED:
-               if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
-                       /*
-                        * If just polling, check to see if we will block.
-                        */
-                       if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
-                           (LK_HAVE_EXCL | LK_WANT_EXCL))) {
-                               error = EBUSY;
-                               break;
-                       }
-                       /*
-                        * Wait for exclusive locks and upgrades to clear.
-                        */
-                       ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
-                           (LK_HAVE_EXCL | LK_WANT_EXCL));
-                       if (error)
-                               break;
-                       lkp->lk_sharecount++;
-                       break;
-               }
-               /*
-                * We hold an exclusive lock, so downgrade it to shared.
-                * An alternative would be to fail with EDEADLK.
-                */
-               lkp->lk_sharecount++;
-
-               if (WEHOLDIT(lkp, pid, cpu_id) == 0 ||
-                   lkp->lk_exclusivecount == 0)
-                       panic("lockmgr: not holding exclusive lock");
-               lkp->lk_sharecount += lkp->lk_exclusivecount;
-               lkp->lk_exclusivecount = 0;
-               lkp->lk_flags &= ~LK_HAVE_EXCL;
-               SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
-               if (lkp->lk_waitcount)
-                       wakeup((void *)(lkp));
-               break;
-
-       case LK_EXCLUSIVE:
-               if (WEHOLDIT(lkp, pid, cpu_id)) {
-                       /*
-                        * Recursive lock.
-                        */
-                       if ((extflags & LK_CANRECURSE) == 0) {
-                               if (extflags & LK_RECURSEFAIL) {
-                                       error = EDEADLK;
-                                       break;
-                               } else
-                                       panic("lockmgr: locking against 
myself");
-                       }
-                       lkp->lk_exclusivecount++;
-                       break;
-               }
-               /*
-                * If we are just polling, check to see if we will sleep.
-                */
-               if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
-                    (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
-                    lkp->lk_sharecount != 0)) {
-                       error = EBUSY;
-                       break;
-               }
-               /*
-                * Try to acquire the want_exclusive flag.
-                */
-               ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
-                   (LK_HAVE_EXCL | LK_WANT_EXCL));
-               if (error)
-                       break;
-               lkp->lk_flags |= LK_WANT_EXCL;
-               /*
-                * Wait for shared locks and upgrades to finish.
-                */
-               ACQUIRE(lkp, error, extflags, 0, lkp->lk_sharecount != 0);
-               lkp->lk_flags &= ~LK_WANT_EXCL;
-               if (error)
-                       break;
-               lkp->lk_flags |= LK_HAVE_EXCL;
-               SETHOLDER(lkp, pid, cpu_id);
-               if (lkp->lk_exclusivecount != 0)
-                       panic("lockmgr: non-zero exclusive count");
-               lkp->lk_exclusivecount = 1;
-               break;
-
-       case LK_RELEASE:
-               if (lkp->lk_exclusivecount != 0) {
-                       if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
-                               panic("lockmgr: pid %d, not exclusive lock "
-                                   "holder %d unlocking",
-                                   pid, lkp->lk_lockholder);
-                       }
-                       lkp->lk_exclusivecount--;
-                       if (lkp->lk_exclusivecount == 0) {
-                               lkp->lk_flags &= ~LK_HAVE_EXCL;
-                               SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
-                       }
-               } else if (lkp->lk_sharecount != 0) {
-                       lkp->lk_sharecount--;
-               }
-#ifdef DIAGNOSTIC
-               else
-                       panic("lockmgr: release of unlocked lock!");
-#endif
-               if (lkp->lk_waitcount)
-                       wakeup((void *)(lkp));
-               break;
-
-       case LK_DRAIN:
-               /*
-                * Check that we do not already hold the lock, as it can 
-                * never drain if we do. Unfortunately, we have no way to
-                * check for holding a shared lock, but at least we can
-                * check for an exclusive one.
-                */
-               if (WEHOLDIT(lkp, pid, cpu_id))
-                       panic("lockmgr: draining against myself");
-               /*
-                * If we are just polling, check to see if we will sleep.
-                */
-               if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
-                    (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
-                    lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)) {
-                       error = EBUSY;
-                       break;
-               }
-               ACQUIRE(lkp, error, extflags, 1,
-                   ((lkp->lk_flags &
-                    (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
-                    lkp->lk_sharecount != 0 ||
-                    lkp->lk_waitcount != 0));
-               if (error)
-                       break;
-               lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
-               SETHOLDER(lkp, pid, cpu_id);
-               lkp->lk_exclusivecount = 1;
-               break;
-
-       default:
-               panic("lockmgr: unknown locktype request %d",
-                   flags & LK_TYPE_MASK);
-               /* NOTREACHED */
-       }
-       if ((lkp->lk_flags & LK_WAITDRAIN) != 0 &&
-           ((lkp->lk_flags &
-           (LK_HAVE_EXCL | LK_WANT_EXCL)) == 0 &&
-           lkp->lk_sharecount == 0 && lkp->lk_waitcount == 0)) {
-               lkp->lk_flags &= ~LK_WAITDRAIN;
-               wakeup((void *)&lkp->lk_flags);
+       if (flags & LK_RELEASE) {
+               rrw_exit(&lkp->lk_lck);
+               return (0);
        }
-       return (error);
-}
 
-#ifdef DIAGNOSTIC
-/*
- * Print out information about state of a lock. Used by VOP_PRINT
- * routines to display status about contained locks.
- */
-void
-lockmgr_printinfo(__volatile struct lock *lkp)
-{
+       if (flags & LK_SHARED)
+               rwflags |= RW_READ;
+       if (flags & (LK_EXCLUSIVE|LK_DRAIN))
+               rwflags |= RW_WRITE;
 
-       if (lkp->lk_sharecount)
-               printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
-                   lkp->lk_sharecount);
-       else if (lkp->lk_flags & LK_HAVE_EXCL) {
-               printf(" lock type %s: EXCL (count %d) by ",
-                   lkp->lk_wmesg, lkp->lk_exclusivecount);
-               printf("pid %d", lkp->lk_lockholder);
-       } else
-               printf(" not locked");
-       if (lkp->lk_waitcount > 0)
-               printf(" with %d pending", lkp->lk_waitcount);
+       if (flags & LK_RECURSEFAIL)
+               rwflags |= RW_RECURSEFAIL;
+       if (flags & LK_NOWAIT)
+               rwflags |= RW_NOSLEEP;
+
+       return (rrw_enter(&lkp->lk_lck, rwflags));
 }
-#endif /* DIAGNOSTIC */
 
 #if defined(MULTIPROCESSOR)
 /*
@@ -343,7 +104,7 @@ lockmgr_printinfo(__volatile struct lock *lkp)
  * so that they show up in profiles.
  */
 
-struct __mp_lock kernel_lock; 
+struct __mp_lock kernel_lock;
 
 void
 _kernel_lock_init(void)
@@ -385,10 +146,4 @@ _kernel_proc_unlock(struct proc *p)
 {
        __mp_unlock(&kernel_lock);
 }
-
-#ifdef MP_LOCKDEBUG
-/* CPU-dependent timing, needs this to be settable from ddb. */
-int __mp_lock_spinout = 200000000;
-#endif
-
 #endif /* MULTIPROCESSOR */
diff --git a/kern/kern_rwlock.c b/kern/kern_rwlock.c
index d22ae3a..a85f8b1 100644
--- a/kern/kern_rwlock.c
+++ b/kern/kern_rwlock.c
@@ -2,27 +2,19 @@
 
 /*
  * Copyright (c) 2002, 2003 Artur Grabowski <a...@openbsd.org>
- * All rights reserved. 
+ * Copyright (c) 2011 Thordur Bjornsson <t...@openbsd.org>
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include <sys/param.h>
@@ -69,6 +61,9 @@ static const struct rwlock_op {
                0,
                PLOCK
        },
+       {       /* Sparse Entry. */
+               0,
+       },
        {       /* RW_DOWNGRADE */
                RWLOCK_READ_INCR - RWLOCK_WRLOCK,
                0,
@@ -191,7 +186,7 @@ rw_enter(struct rwlock *rwl, int flags)
        unsigned long inc, o;
        int error;
 
-       op = &rw_ops[flags & RW_OPMASK];
+       op = &rw_ops[(flags & RW_OPMASK) - 1];
 
        inc = op->inc + RW_PROC(curproc) * op->proc_mult;
 retry:
@@ -258,6 +253,13 @@ rw_exit(struct rwlock *rwl)
                wakeup(rwl);
 }
 
+int
+rw_status(struct rwlock *rwl)
+{
+
+       return (rwl->rwl_owner != 0L);
+}
+
 #ifdef DIAGNOSTIC
 void
 rw_assert_wrlock(struct rwlock *rwl)
@@ -283,3 +285,55 @@ rw_assert_unlocked(struct rwlock *rwl)
                panic("%s: lock held", rwl->rwl_name);
 }
 #endif
+
+/* recursive rwlocks; */
+void
+rrw_init(struct rrwlock *rrwl, char *name)
+{
+       bzero(rrwl, sizeof(struct rrwlock));
+       rw_init(&rrwl->rrwl_lock, name);
+}
+
+int
+rrw_enter(struct rrwlock *rrwl, int flags)
+{
+       int     rv;
+
+       if (RWLOCK_OWNER(&rrwl->rrwl_lock) ==
+           (struct proc *)RW_PROC(curproc)) {
+               if (flags & RW_RECURSEFAIL)
+                       return (EDEADLK);
+               else {
+                       rrwl->rrwl_wcnt++;
+                       return (0);
+               }
+       }
+
+       rv = rw_enter(&rrwl->rrwl_lock, flags);
+       if (rv == 0)
+               rrwl->rrwl_wcnt = 1;
+
+       return (rv);
+}
+
+void
+rrw_exit(struct rrwlock *rrwl)
+{
+
+       if (RWLOCK_OWNER(&rrwl->rrwl_lock) ==
+           (struct proc *)RW_PROC(curproc)) {
+               KASSERT(rrwl->rrwl_wcnt > 0);
+               rrwl->rrwl_wcnt--;
+               if (rrwl->rrwl_wcnt != 0)
+                       return;
+       }
+
+       rw_exit(&rrwl->rrwl_lock);
+}
+
+int
+rrw_status(struct rrwlock *rrwl)
+{
+
+       return (rw_status(&rrwl->rrwl_lock));
+}
diff --git a/sys/lock.h b/sys/lock.h
index 54dbf3b..13ddeb3 100644
--- a/sys/lock.h
+++ b/sys/lock.h
@@ -42,6 +42,8 @@
 #include <machine/lock.h>
 #endif
 
+#include <sys/rwlock.h>
+
 struct simplelock {
 };
 
@@ -53,123 +55,27 @@ typedef struct simplelock       *simple_lock_t;
 #define        simple_lock_try(lkp)    (1)     /* always succeeds */
 #define        simple_unlock(lkp)
 #define simple_lock_assert(lkp)
-
-static __inline void simple_lock_init(struct simplelock *lkp)
-{
-}
-
+#define simple_lock_init(lkp)
 #endif /* _KERNEL */
 
-typedef struct lock             lock_data_t;
-typedef struct lock             *lock_t;
-
-/*
- * The general lock structure.  Provides for multiple shared locks,
- * upgrading from shared to exclusive, and sleeping until the lock
- * can be gained. The simple locks are defined in <machine/param.h>.
- */
 struct lock {
-       u_int   lk_flags;               /* see below */
-       int     lk_sharecount;          /* # of accepted shared locks */
-       int     lk_waitcount;           /* # of processes sleeping for lock */
-       int     lk_exclusivecount;      /* # of recursive exclusive locks */
-
-       /*
-        * This is the sleep message for sleep locks, and a simple name
-        * for spin locks.
-        */
-       char    *lk_wmesg;              /* resource sleeping (for tsleep) */
-
-       /* pid of exclusive lock holder */
-       pid_t lk_lockholder;
-
-       /* priority at which to sleep */
-       int lk_prio;
-
-       /* maximum sleep time (for tsleep) */
-       int lk_timo;
+       struct rrwlock  lk_lck;
 };
 
-/*
- * Lock request types:
- *   LK_SHARED - get one of many possible shared locks. If a process
- *     holding an exclusive lock requests a shared lock, the exclusive
- *     lock(s) will be downgraded to shared locks.
- *   LK_EXCLUSIVE - stop further shared locks, when they are cleared,
- *     grant a pending upgrade if it exists, then grant an exclusive
- *     lock. Only one exclusive lock may exist at a time, except that
- *     a process holding an exclusive lock may get additional exclusive
- *     locks if it explicitly sets the LK_CANRECURSE flag in the lock
- *     request, or if the LK_CANRECUSE flag was set when the lock was
- *     initialized.
- *   LK_RELEASE - release one instance of a lock.
- *   LK_DRAIN - wait for all activity on the lock to end, then mark it
- *     decommissioned. This feature is used before freeing a lock that
- *     is part of a piece of memory that is about to be freed.
- *
- * These are flags that are passed to the lockmgr routine.
- */
-#define LK_TYPE_MASK   0x0000000f      /* type of lock sought */
-#define LK_SHARED      0x00000001      /* shared lock */
-#define LK_EXCLUSIVE   0x00000002      /* exclusive lock */
-#define LK_RELEASE     0x00000006      /* release any type of lock */
-#define LK_DRAIN       0x00000007      /* wait for all lock activity to end */
-/*
- * External lock flags.
- *
- * The first three flags may be set in lock_init to set their mode permanently,
- * or passed in as arguments to the lock manager.
- */
-#define LK_EXTFLG_MASK 0x00200070      /* mask of external flags */
-#define LK_NOWAIT      0x00000010      /* do not sleep to await lock */
-#define LK_CANRECURSE  0x00000040      /* allow recursive exclusive lock */
-#define LK_RECURSEFAIL 0x00200000      /* fail if recursive exclusive lock */
-/*
- * Internal lock flags.
- *
- * These flags are used internally to the lock manager.
- */
-#define LK_WANT_EXCL   0x00002000      /* exclusive lock sought */
-#define LK_HAVE_EXCL   0x00004000      /* exclusive lock obtained */
-#define LK_WAITDRAIN   0x00008000      /* process waiting for lock to drain */
-#define LK_DRAINING    0x00040000      /* lock is being drained */
-#define LK_DRAINED     0x00080000      /* lock has been decommissioned */
-/*
- * Control flags
- *
- * Non-persistent external flags.
- */
-#define LK_RETRY       0x00020000      /* vn_lock: retry until locked */
-
-/*
- * Lock return status.
- *
- * Successfully obtained locks return 0. Locks will always succeed
- * unless one of the following is true:
- *     LK_NOWAIT is set and a sleep would be required (returns EBUSY).
- *     PCATCH is set in lock priority and a signal arrives (returns
- *         either EINTR or ERESTART if system calls is to be restarted).
- *     Non-null lock timeout and timeout expires (returns EWOULDBLOCK).
- * A failed lock attempt always returns a non-zero error value. No lock
- * is held after an error return.
- */
-
-/*
- * Indicator that no process holds exclusive lock
- */
-#define LK_KERNPROC ((pid_t) -2)
-#define LK_NOPROC ((pid_t) -1)
-#define LK_NOCPU ((cpuid_t) -1)
-
-void   lockinit(struct lock *, int prio, char *wmesg, int timo,
-                       int flags);
-int    lockmgr(__volatile struct lock *, u_int flags, void *);
-void   lockmgr_printinfo(__volatile struct lock *);
+#define LK_SHARED      0x01    /* shared lock */
+#define LK_EXCLUSIVE   0x02    /* exclusive lock */
+#define LK_TYPE_MASK   0x03    /* type of lock sought */
+#define LK_DRAIN       0x04    /* wait for all lock activity to end */
+#define LK_RELEASE     0x08    /* release any type of lock */
+#define LK_NOWAIT      0x10    /* do not sleep to await lock */
+#define LK_CANRECURSE  0x20    /* allow recursive exclusive lock */
+#define LK_RECURSEFAIL 0x40    /* fail if recursive exclusive lock */
+#define LK_RETRY       0x80    /* vn_lock: retry until locked */
+
+void   lockinit(struct lock *, int, char *, int, int);
+int    lockmgr(struct lock *, u_int flags, void *);
 int    lockstatus(struct lock *);
 
-int    spinlock_release_all(__volatile struct lock *);
-void   spinlock_acquire_count(__volatile struct lock *, int);
-
-#define LOCK_ASSERT(x) /* nothing */
+#define        lockmgr_printinfo(lkp)
 
 #endif /* !_LOCK_H_ */
diff --git a/sys/rwlock.h b/sys/rwlock.h
index 5629ad2..969250d 100644
--- a/sys/rwlock.h
+++ b/sys/rwlock.h
@@ -1,27 +1,18 @@
 /*     $OpenBSD$       */
 /*
  * Copyright (c) 2002 Artur Grabowski <a...@openbsd.org>
- * All rights reserved. 
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
 /*
@@ -43,7 +34,7 @@
  * optimized by machine dependent code when __HAVE_MD_RWLOCK is defined.
  *
  * MD code that defines __HAVE_MD_RWLOCK and implement four functions:
- *  
+ *
  * void rw_enter_read(struct rwlock *)
  *  atomically test for RWLOCK_WRLOCK and if not set, increment the lock
  *  by RWLOCK_READ_INCR. While RWLOCK_WRLOCK is set, loop into rw_enter_wait.
@@ -68,7 +59,6 @@
 #ifndef SYS_RWLOCK_H
 #define SYS_RWLOCK_H
 
-
 struct proc;
 
 struct rwlock {
@@ -107,17 +97,31 @@ void rw_assert_unlocked(struct rwlock *);
 
 int rw_enter(struct rwlock *, int);
 void rw_exit(struct rwlock *);
-#define RW_WRITE       0x00UL          /* exclusive lock */    
-#define RW_READ                0x01UL          /* shared lock */
-#define RW_DOWNGRADE   0x02UL          /* downgrade exclusive to shared */
-#define RW_OPMASK      0x03UL
+int rw_status(struct rwlock *);
+
+#define RW_WRITE       0x0001UL        /* exclusive lock */
+#define RW_READ                0x0002UL        /* shared lock */
+#define RW_DOWNGRADE   0x0004UL        /* downgrade exclusive to shared */
+#define RW_OPMASK      0x0007UL
 
-#define RW_INTR                0x10UL          /* interruptible sleep */
-#define RW_SLEEPFAIL   0x20UL          /* fail if we slept for the lock */
-#define RW_NOSLEEP     0x40UL          /* don't wait for the lock */
+#define RW_INTR                0x0010UL        /* interruptible sleep */
+#define RW_SLEEPFAIL   0x0020UL        /* fail if we slept for the lock */
+#define RW_NOSLEEP     0x0040UL        /* don't wait for the lock */
+#define RW_RECURSEFAIL 0x0080UL        /* Fail on recursion for RRW locks. */
 
 #ifndef rw_cas
 int rw_cas(volatile unsigned long *, unsigned long, unsigned long);
 #endif
 
+/* recursive rwlocks; */
+struct rrwlock {
+       struct rwlock   rrwl_lock;
+       uint32_t        rrwl_wcnt;      /* # writers. */
+};
+
+void   rrw_init(struct rrwlock *, char *);
+int    rrw_enter(struct rrwlock *, int);
+void   rrw_exit(struct rrwlock *);
+int    rrw_status(struct rrwlock *);
+
 #endif

Reply via email to