--- /usr/src/sys/kern/kern_rwlock.c	Tue Apr  3 22:17:21 2007
+++ kern_rwlock.c	Tue Apr  3 22:07:46 2007
@@ -40,12 +40,12 @@
 #include <sys/param.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
+#include <sys/lock_profile.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/rwlock.h>
 #include <sys/systm.h>
 #include <sys/turnstile.h>
-#include <sys/lock_profile.h>
 #include <machine/cpu.h>
 
 #if defined(SMP) && !defined(NO_ADAPTIVE_RWLOCKS)
@@ -79,6 +79,17 @@
 	    (struct thread *)RW_OWNER((rw)->rw_lock))
 
 /*
+ * Returns if a write owner is recursed.  Write ownership is not assured
+ * here and should be previously checked.
+ */
+#define	rw_recursed(rw)		((rw)->rw_recurse != 0)
+
+/*
+ * Return true if curthread helds the lock.
+ */
+#define rw_wlocked(rw)		(rw_wowner((rw)) == curthread)
+
+/*
  * Return a pointer to the owning thread for this lock who should receive
  * any priority lent by threads that block on this lock.  Currently this
  * is identical to rw_wowner().
@@ -118,14 +129,26 @@
 }
 
 void
-rw_init(struct rwlock *rw, const char *name)
+rw_init_flags(struct rwlock *rw, const char *name, int opts)
 {
+	int flags;
 
-	rw->rw_lock = RW_UNLOCKED;
+	flags = LO_UPGRADABLE;
+	if (opts & RW_DUPOK)
+		flags |= LO_DUPOK;
+	if (opts & RW_NOPROFILE)
+		flags |= LO_NOPROFILE;
+	if (!(opts & RW_NOWITNESS))
+		flags |= LO_WITNESS;
+	if (opts & RW_QUIET)
+		flags |= LO_QUIET;
+	if (opts & RW_RECURSE)
+		flags |= LO_RECURSABLE;
 
+	rw->rw_lock = RW_UNLOCKED;
+	rw->rw_recurse = 0;
 	lock_profile_object_init(&rw->lock_object, &lock_class_rw, name);
-	lock_init(&rw->lock_object, &lock_class_rw, name, NULL, LO_WITNESS |
-	    LO_RECURSABLE | LO_UPGRADABLE);
+	lock_init(&rw->lock_object, &lock_class_rw, name, NULL, flags);
 }
 
 void
@@ -133,6 +156,7 @@
 {
 
 	KASSERT(rw->rw_lock == RW_UNLOCKED, ("rw lock not unlocked"));
+	KASSERT(rw->rw_recurse == 0, ("rw lock still recursed"));
 	lock_profile_object_destroy(&rw->lock_object);
 	lock_destroy(&rw->lock_object);
 }
@@ -157,13 +181,10 @@
 {
 
 	MPASS(curthread != NULL);
-	KASSERT(rw_wowner(rw) != curthread,
-	    ("%s (%s): wlock already held @ %s:%d", __func__,
-	    rw->lock_object.lo_name, file, line));
 	WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
 	    line);
 	__rw_wlock(rw, curthread, file, line);
-	LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, 0, file, line);
+	LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, rw->rw_recurse, file, line);
 	WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
 	curthread->td_locks++;
 }
@@ -176,11 +197,43 @@
 	_rw_assert(rw, RA_WLOCKED, file, line);
 	curthread->td_locks--;
 	WITNESS_UNLOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
-	LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, 0, file, line);
-	lock_profile_release_lock(&rw->lock_object);
+	LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, rw->rw_recurse, file,
+	    line);
 	__rw_wunlock(rw, curthread, file, line);
 }
 
+int
+_rw_try_wlock(struct rwlock *rw, const char *file, int line)
+{
+	uintptr_t tid;
+
+	MPASS(curthread != NULL);
+
+	if (rw_wlocked(rw)) {
+		KASSERT(rw->lock_object.lo_flags & LO_RECURSABLE,
+		    ("%s: %p recursing but not-recursable @ %s:%d\n", __func__,
+		    rw, file, line));
+		rw->rw_recurse++;
+		atomic_set_ptr(&rw->rw_lock, RW_LOCK_RECURSED);
+		if (LOCK_LOG_TEST(&rw->lock_object, 0))
+			CTR2(KTR_LOCK, "%s: %p recursing", __func__, rw);
+		return (1);
+	}
+
+	tid = (uintptr_t)curthread;
+	if (_rw_write_lock(rw, tid)) {
+		LOCK_LOG_TRY("WLOCK", &rw->lock_object, 0, 1, file, line);
+		WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
+		    file, line);
+		curthread->td_locks++;
+		return (1);
+	}
+
+	LOCK_LOG_TRY("WLOCK", &rw->lock_object, 0, 0, file, line);
+	return (0);
+}
+
+
 void
 _rw_rlock(struct rwlock *rw, const char *file, int line)
 {
@@ -191,9 +244,6 @@
 	int contested = 0;
 	uintptr_t x;
 
-	KASSERT(rw_wowner(rw) != curthread,
-	    ("%s (%s): wlock already held @ %s:%d", __func__,
-	    rw->lock_object.lo_name, file, line));
 	WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line);
 
 	/*
@@ -236,15 +286,13 @@
 					    (void *)(x + RW_ONE_READER));
 				if (RW_READERS(x) == 0)
 					lock_profile_obtain_lock_success(
-					    &rw->lock_object, contested, waittime,
-					    file, line);
+					    &rw->lock_object, contested,
+					    waittime, file, line);
 				break;
 			}
 			cpu_spinwait();
 			continue;
 		}
-		lock_profile_obtain_lock_failed(&rw->lock_object, &contested,
-		    &waittime);
 
 		/*
 		 * Okay, now it's the hard case.  Some other thread already
@@ -295,6 +343,8 @@
 			if (LOCK_LOG_TEST(&rw->lock_object, 0))
 				CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
 				    __func__, rw, owner);
+			lock_profile_obtain_lock_failed(&rw->lock_object,
+			    &contested, &waittime);
 			while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
 			    TD_IS_RUNNING(owner))
 				cpu_spinwait();
@@ -309,6 +359,8 @@
 		if (LOCK_LOG_TEST(&rw->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
 			    rw);
+		lock_profile_obtain_lock_failed(&rw->lock_object, &contested,
+		    &waittime);
 		turnstile_wait(&rw->lock_object, rw_owner(rw), TS_SHARED_QUEUE);
 		if (LOCK_LOG_TEST(&rw->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
@@ -385,6 +437,7 @@
 				if (LOCK_LOG_TEST(&rw->lock_object, 0))
 					CTR2(KTR_LOCK, "%s: %p last succeeded",
 					    __func__, rw);
+				lock_profile_release_lock(&rw->lock_object);
 				break;
 			}
 			continue;
@@ -436,11 +489,29 @@
 		 */
 		ts = turnstile_lookup(&rw->lock_object);
 		MPASS(ts != NULL);
+		lock_profile_release_lock(&rw->lock_object);
 		turnstile_broadcast(ts, TS_EXCLUSIVE_QUEUE);
 		turnstile_unpend(ts, TS_SHARED_LOCK);
 		break;
 	}
-	lock_profile_release_lock(&rw->lock_object);
+}
+
+int
+_rw_try_rlock(struct rwlock *rw, const char *file, int line)
+{
+	uintptr_t x;
+
+	x = rw->rw_lock;
+	if ((x & RW_LOCK_READ) && atomic_cmpset_acq_ptr(&rw->rw_lock, x,
+	    x + RW_ONE_READER)) {
+		LOCK_LOG_TRY("RLOCK", &rw->lock_object, 0, 1, file, line);
+		WITNESS_LOCK(&rw->lock_object, LOP_TRYLOCK, file, line);
+		curthread->td_locks++;
+		return (1);
+	}
+
+	LOCK_LOG_TRY("RLOCK", &rw->lock_object, 0, 0, file, line);
+	return (0);
 }
 
 /*
@@ -454,8 +525,21 @@
 #ifdef ADAPTIVE_RWLOCKS
 	volatile struct thread *owner;
 #endif
+	uint64_t waittime = 0;
+	int contested = 0;
 	uintptr_t v;
 
+	if (rw_wlocked(rw)) {
+		KASSERT(rw->lock_object.lo_flags & LO_RECURSABLE,
+		    ("%s: %p recursing but not-recursable @ %s:%d\n", __func__,
+		    rw, file, line));
+		rw->rw_recurse++;
+		atomic_set_ptr(&rw->rw_lock, RW_LOCK_RECURSED);
+		if (LOCK_LOG_TEST(&rw->lock_object, 0))
+			CTR2(KTR_LOCK, "%s: %p recursing", __func__, rw);
+		return;
+	}
+
 	if (LOCK_LOG_TEST(&rw->lock_object, 0))
 		CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
 		    rw->lock_object.lo_name, (void *)rw->rw_lock, file, line);
@@ -527,6 +611,8 @@
 			if (LOCK_LOG_TEST(&rw->lock_object, 0))
 				CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
 				    __func__, rw, owner);
+			lock_profile_obtain_lock_failed(&rw->lock_object,
+			    &contested, &waittime);
 			while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
 			    TD_IS_RUNNING(owner))
 				cpu_spinwait();
@@ -541,12 +627,17 @@
 		if (LOCK_LOG_TEST(&rw->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
 			    rw);
+		lock_profile_obtain_lock_failed(&rw->lock_object, &contested,
+		    &waittime);
 		turnstile_wait(&rw->lock_object, rw_owner(rw),
 		    TS_EXCLUSIVE_QUEUE);
 		if (LOCK_LOG_TEST(&rw->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
 			    __func__, rw);
 	}
+
+	lock_profile_obtain_lock_success(&rw->lock_object, contested, waittime,
+	    file, line);
 }
 
 /*
@@ -561,8 +652,16 @@
 	uintptr_t v;
 	int queue;
 
+	if (rw_wlocked(rw) && rw_recursed(rw)) {
+		if ((--rw->rw_recurse) == 0)
+			atomic_clear_ptr(&rw->rw_lock, RW_LOCK_RECURSED);
+		if (LOCK_LOG_TEST(&rw->lock_object, 0))
+			CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, rw);
+		return;
+	}
+
 	KASSERT(rw->rw_lock & (RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS),
-	    ("%s: neither of the waiter flags are set", __func__));
+	    ("%s: neither of the waiters flags are set", __func__));
 
 	if (LOCK_LOG_TEST(&rw->lock_object, 0))
 		CTR2(KTR_LOCK, "%s: %p contested", __func__, rw);
@@ -641,6 +740,7 @@
 	if (LOCK_LOG_TEST(&rw->lock_object, 0))
 		CTR3(KTR_LOCK, "%s: %p waking up %s waiters", __func__, rw,
 		    queue == TS_SHARED_QUEUE ? "read" : "write");
+	lock_profile_release_lock(&rw->lock_object);
 	turnstile_broadcast(ts, queue);
 	atomic_store_rel_ptr(&rw->rw_lock, v);
 	turnstile_unpend(ts, TS_EXCLUSIVE_LOCK);
@@ -716,7 +816,7 @@
 	struct turnstile *ts;
 	uintptr_t tid, v;
 
-	_rw_assert(rw, RA_WLOCKED, file, line);
+	_rw_assert(rw, RA_WLOCKED | RA_NOTRECURSED, file, line);
 
 	WITNESS_DOWNGRADE(&rw->lock_object, 0, file, line);
 
@@ -796,7 +896,8 @@
 		return;
 	switch (what) {
 	case RA_LOCKED:
-	case RA_LOCKED | LA_NOTRECURSED:
+	case RA_LOCKED | RA_RECURSED:
+	case RA_LOCKED | RA_NOTRECURSED:
 	case RA_RLOCKED:
 #ifdef WITNESS
 		witness_assert(&rw->lock_object, what, file, line);
@@ -812,11 +913,31 @@
 			panic("Lock %s not %slocked @ %s:%d\n",
 			    rw->lock_object.lo_name, (what == RA_RLOCKED) ?
 			    "read " : "", file, line);
+
+		if (!(rw->rw_lock & RW_LOCK_READ)) {
+			if (rw_recursed(rw)) {
+				if (what & RA_NOTRECURSED)
+					panic("Lock %s recursed @ %s:%d\n",
+					    rw->lock_object.lo_name, file,
+					    line);
+			} else if (what & RA_RECURSED)
+				panic("Lock %s not recursed @ %s:%d\n",
+				    rw->lock_object.lo_name, file, line);
+		}
 #endif
 		break;
 	case RA_WLOCKED:
+	case RA_WLOCKED | RA_RECURSED:
+	case RA_WLOCKED | RA_NOTRECURSED:
 		if (rw_wowner(rw) != curthread)
 			panic("Lock %s not exclusively locked @ %s:%d\n",
+			    rw->lock_object.lo_name, file, line);
+		if (rw_recursed(rw)) {
+			if (what & RA_NOTRECURSED)
+				panic("Lock %s recursed @ %s:%d\n",
+				    rw->lock_object.lo_name, file, line);
+		} else if (what & RA_RECURSED)
+			panic("Lock %s not recursed @ %s:%d\n",
 			    rw->lock_object.lo_name, file, line);
 		break;
 	case RA_UNLOCKED:
--- /usr/src/sys/kern/kern_sx.c	Tue Apr  3 22:16:25 2007
+++ kern_sx.c	Tue Apr  3 22:08:38 2007
@@ -170,7 +170,9 @@
 {
 	int flags;
 
-	flags = LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE;
+	flags = LO_SLEEPABLE | LO_UPGRADABLE;
+	if (opts & SX_RECURSE)
+		flags |= LO_RECURSABLE;
 	if (opts & SX_DUPOK)
 		flags |= LO_DUPOK;
 	if (opts & SX_NOPROFILE)
@@ -248,6 +250,9 @@
 	MPASS(curthread != NULL);
 
 	if (sx_xlocked(sx)) {
+		KASSERT(sx->lock_object.lo_flags & LO_RECURSABLE,
+		    ("%s: %p recursing but not-recursable @ %s:%d\n", __func__,
+		    sx, file, line));
 		sx->sx_recurse++;
 		atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
 		rval = 1;
@@ -273,7 +278,6 @@
 	curthread->td_locks--;
 	WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
 	LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
-	lock_profile_release_lock(&sx->lock_object);
 	__sx_sunlock(sx, file, line);
 }
 
@@ -287,7 +291,6 @@
 	WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
 	LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
 	    line);
-	lock_profile_release_lock(&sx->lock_object);
 	__sx_xunlock(sx, curthread, file, line);
 }
 
@@ -389,10 +392,15 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waittime;
 	uintptr_t x;
+	int contested;
 
 	/* If we already hold an exclusive lock, then recurse. */
 	if (sx_xlocked(sx)) {
+		KASSERT(sx->lock_object.lo_flags & LO_RECURSABLE,
+		    ("%s: %p recursing but not-recursable @ %s:%d\n", __func__,
+		    sx, file, line));
 		sx->sx_recurse++;
 		atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
@@ -404,6 +412,8 @@
 		CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
 		    sx->lock_object.lo_name, (void *)sx->sx_lock, file, line);
 
+	waittime = 0;
+	contested = 0;
 	while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) {
 #ifdef ADAPTIVE_SX
 		/*
@@ -421,6 +431,8 @@
 					CTR3(KTR_LOCK,
 					    "%s: spinning on %p held by %p",
 					    __func__, sx, owner);
+				lock_profile_obtain_lock_failed(
+				    &sx->lock_object, &contested, &waittime);
 				GIANT_SAVE();
 				while (SX_OWNER(sx->sx_lock) == x &&
 				    TD_IS_RUNNING(owner))
@@ -507,6 +519,8 @@
 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
 			    __func__, sx);
 
+		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
+		    &waittime);
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
 		    SLEEPQ_SX, SQ_EXCLUSIVE_QUEUE);
@@ -518,6 +532,8 @@
 	}
 
 	GIANT_RESTORE();
+	lock_profile_obtain_lock_success(&sx->lock_object, contested, waittime,
+	    file, line);
 }
 
 /*
@@ -568,6 +584,7 @@
 		    __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
 		    "exclusive");
 	atomic_store_rel_ptr(&sx->sx_lock, x);
+	lock_profile_release_lock(&sx->lock_object);
 	sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, -1, queue);
 }
 
@@ -584,12 +601,16 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waittime;
 	uintptr_t x;
+	int contested;
 
 	/*
 	 * As with rwlocks, we don't make any attempt to try to block
 	 * shared locks once there is an exclusive waiter.
 	 */
+	waittime = 0;
+	contested = 0;
 	for (;;) {
 		x = sx->sx_lock;
 
@@ -608,6 +629,10 @@
 					    "%s: %p succeed %p -> %p", __func__,
 					    sx, (void *)x,
 					    (void *)(x + SX_ONE_SHARER));
+				if (SX_SHARERS(x) == 0)
+					lock_profile_obtain_lock_success(
+					    &sx->lock_object, contested,
+					    waittime, file, line);
 				break;
 			}
 			continue;
@@ -627,6 +652,8 @@
 					CTR3(KTR_LOCK,
 					    "%s: spinning on %p held by %p",
 					    __func__, sx, owner);
+				lock_profile_obtain_lock_failed(
+				    &sx->lock_object, &contested, &waittime);
 				GIANT_SAVE();
 				while (SX_OWNER(sx->sx_lock) == x &&
 				    TD_IS_RUNNING(owner))
@@ -692,6 +719,8 @@
 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
 			    __func__, sx);
 
+		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
+		    &waittime);
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
 		    SLEEPQ_SX, SQ_SHARED_QUEUE);
@@ -754,6 +783,7 @@
 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
 					CTR2(KTR_LOCK, "%s: %p last succeeded",
 					    __func__, sx);
+				lock_profile_release_lock(&sx->lock_object);
 				break;
 			}
 			continue;
@@ -782,6 +812,7 @@
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p waking up all thread on"
 			    "exclusive queue", __func__, sx);
+		lock_profile_release_lock(&sx->lock_object);
 		sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, -1,
 		    SQ_EXCLUSIVE_QUEUE);
 		break;
--- /usr/src/sys/sys/_rwlock.h	Tue Apr  3 22:16:04 2007
+++ _rwlock.h	Mon Apr  2 05:33:18 2007
@@ -38,6 +38,7 @@
 struct rwlock {
 	struct lock_object	lock_object;
 	volatile uintptr_t	rw_lock;
+	volatile unsigned	rw_recurse;
 };
 
 #endif /* !_SYS__RWLOCK_H_ */
--- /usr/src/sys/sys/rwlock.h	Tue Apr  3 22:16:36 2007
+++ rwlock.h	Tue Apr  3 21:47:01 2007
@@ -65,11 +65,13 @@
 #define	RW_LOCK_READ		0x01
 #define	RW_LOCK_READ_WAITERS	0x02
 #define	RW_LOCK_WRITE_WAITERS	0x04
+#define	RW_LOCK_RECURSED	0x08
 #define	RW_LOCK_FLAGMASK						\
-	(RW_LOCK_READ | RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS)
+	(RW_LOCK_READ | RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS |	\
+	RW_LOCK_RECURSED)
 
 #define	RW_OWNER(x)		((x) & ~RW_LOCK_FLAGMASK)
-#define	RW_READERS_SHIFT	3
+#define	RW_READERS_SHIFT	4
 #define	RW_READERS(x)		(RW_OWNER((x)) >> RW_READERS_SHIFT)
 #define	RW_READERS_LOCK(x)	((x) << RW_READERS_SHIFT | RW_LOCK_READ)
 #define	RW_ONE_READER		(1 << RW_READERS_SHIFT)
@@ -97,16 +99,12 @@
 /* Acquire a write lock. */
 #define	__rw_wlock(rw, tid, file, line) do {	\
 	uintptr_t _tid = (uintptr_t)(tid);				\
-	int contested = 0;                                              \
-        uint64_t waitstart = 0;                                         \
 						                        \
-	if (!_rw_write_lock((rw), _tid)) {				\
-		lock_profile_obtain_lock_failed(&(rw)->lock_object,	\
-		    &contested, &waitstart);				\
+	if (!_rw_write_lock((rw), _tid))				\
 		_rw_wlock_hard((rw), _tid, (file), (line));		\
-	}                                                               \
-	lock_profile_obtain_lock_success(&(rw)->lock_object, contested,	\
-	    waitstart, (file), (line));					\
+	else								\
+		lock_profile_obtain_lock_success(&(rw)->lock_object, 0,	\
+		    0, (file), (line));					\
 } while (0)
 
 /* Release a write lock. */
@@ -115,6 +113,8 @@
 									\
 	if (!_rw_write_unlock((rw), _tid))				\
 		_rw_wunlock_hard((rw), _tid, (file), (line));		\
+	else								\
+		lock_profile_release_lock(&(rw)->lock_object);		\
 } while (0)
 
 /*
@@ -123,14 +123,17 @@
  * be used instead.
  */
 
-void	rw_init(struct rwlock *rw, const char *name);
+#define	rw_init(rw, name)	rw_init_flags((rw), (name), 0)
+void	rw_init_flags(struct rwlock *rw, const char *name, int opts);
 void	rw_destroy(struct rwlock *rw);
 void	rw_sysinit(void *arg);
 int	rw_wowned(struct rwlock *rw);
 void	_rw_wlock(struct rwlock *rw, const char *file, int line);
 void	_rw_wunlock(struct rwlock *rw, const char *file, int line);
+int	_rw_try_wlock(struct rwlock *rw, const char *file, int line);
 void	_rw_rlock(struct rwlock *rw, const char *file, int line);
 void	_rw_runlock(struct rwlock *rw, const char *file, int line);
+int	_rw_try_rlock(struct rwlock *rw, const char *file, int line);
 void	_rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file,
 	    int line);
 void	_rw_wunlock_hard(struct rwlock *rw, uintptr_t tid, const char *file,
@@ -143,8 +146,6 @@
 
 /*
  * Public interface for lock operations.
- *
- * XXX: Missing try locks.
  */
 
 #ifndef LOCK_DEBUG
@@ -165,6 +166,8 @@
 #define	rw_downgrade(rw)	_rw_downgrade((rw), LOCK_FILE, LOCK_LINE)
 #define	rw_sleep(chan, rw, pri, wmesg, timo)				\
 	_sleep((chan), &(rw)->lock_object, (pri), (wmesg), (timo))
+#define	rw_try_wlock(rw)	_rw_try_wlock((rw), LOCK_FILE, LOCK_LINE)
+#define	rw_try_rlock(rw)	_rw_try_rlock((rw), LOCK_FILE, LOCK_LINE)
 
 #define	rw_initialized(rw)	lock_initalized(&(rw)->lock_object)
 
@@ -184,6 +187,15 @@
 	    rw_destroy, (rw))
 
 /*
+ * Options passed to rw_init_flags().
+ */
+#define	RW_DUPOK	0x01
+#define	RW_NOPROFILE	0x02
+#define	RW_NOWITNESS	0x04
+#define	RW_QUIET	0x08
+#define	RW_RECURSE	0x10
+
+/*
  * The INVARIANTS-enabled rw_assert() functionality.
  *
  * The constants need to be defined for INVARIANT_SUPPORT infrastructure
@@ -195,6 +207,8 @@
 #define	RA_RLOCKED		LA_SLOCKED
 #define	RA_WLOCKED		LA_XLOCKED
 #define	RA_UNLOCKED		LA_UNLOCKED
+#define	RA_RECURSED		LA_RECURSED
+#define	RA_NOTRECURSED		LA_NOTRECURSED
 #endif
 
 #ifdef INVARIANTS
--- /usr/src/sys/sys/sx.h	Tue Apr  3 22:16:46 2007
+++ sx.h	Tue Apr  3 21:47:54 2007
@@ -97,17 +97,13 @@
 /* Acquire an exclusive lock. */
 #define	__sx_xlock(sx, tid, file, line) do {				\
 	uintptr_t _tid = (uintptr_t)(tid);				\
-	int contested = 0;                                              \
-        uint64_t waitstart = 0;                                         \
 									\
 	if (!atomic_cmpset_acq_ptr(&(sx)->sx_lock, SX_LOCK_UNLOCKED,	\
-	    _tid)) {							\
-		lock_profile_obtain_lock_failed(&(sx)->lock_object,	\
-		    &contested, &waitstart);				\
+	    _tid))							\
 		_sx_xlock_hard((sx), _tid, (file), (line));		\
-	}								\
-	lock_profile_obtain_lock_success(&(sx)->lock_object, contested,	\
-	    waitstart, (file), (line));					\
+	else								\
+		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
+		    0, (file), (line));					\
 } while (0)
 
 /* Release an exclusive lock. */
@@ -117,23 +113,21 @@
 	if (!atomic_cmpset_rel_ptr(&(sx)->sx_lock, _tid,		\
 	    SX_LOCK_UNLOCKED))						\
 		_sx_xunlock_hard((sx), _tid, (file), (line));		\
+	else								\
+		lock_profile_release_lock(&(sx)->lock_object);		\
 } while (0)
 
 /* Acquire a shared lock. */
 #define	__sx_slock(sx, file, line) do {					\
 	uintptr_t x = (sx)->sx_lock;					\
-	int contested = 0;                                              \
-        uint64_t waitstart = 0;                                         \
 									\
 	if (!(x & SX_LOCK_SHARED) ||					\
 	    !atomic_cmpset_acq_ptr(&(sx)->sx_lock, x,			\
-	    x + SX_ONE_SHARER)) {					\
-		lock_profile_obtain_lock_failed(&(sx)->lock_object,	\
-		    &contested, &waitstart);				\
+	    x + SX_ONE_SHARER))						\
 		_sx_slock_hard((sx), (file), (line));			\
-	}								\
-	lock_profile_obtain_lock_success(&(sx)->lock_object, contested,	\
-	    waitstart, (file), (line));					\
+	else if (SX_SHARERS(x) == 0)					\
+		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
+		    0, (file), (line));					\
 } while (0)
 
 /*
@@ -149,6 +143,8 @@
 	if (x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS) ||	\
 	    !atomic_cmpset_ptr(&(sx)->sx_lock, x, x - SX_ONE_SHARER))	\
 		_sx_sunlock_hard((sx), (file), (line));			\
+	else								\
+		lock_profile_release_lock(&(sx)->lock_object);		\
 } while (0)
 
 /*
@@ -241,6 +237,7 @@
 #define	SX_NOWITNESS		0x04
 #define	SX_QUIET		0x08
 #define	SX_ADAPTIVESPIN		0x10
+#define	SX_RECURSE		0x20
 
 /*
  * XXX: These options should be renamed as SA_*
