--- /usr/src/sys/kern/kern_sx.c	Wed Apr  4 19:05:31 2007
+++ kern_sx.c	Wed Apr  4 19:05:42 2007
@@ -170,7 +170,7 @@
 {
 	int flags;
 
-	flags = LO_SLEEPABLE | LO_UPGRADABLE | LO_RECURSABLE;
+	flags = LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE;
 	if (opts & SX_DUPOK)
 		flags |= LO_DUPOK;
 	if (opts & SX_NOPROFILE)
@@ -273,7 +273,15 @@
 	curthread->td_locks--;
 	WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
 	LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
-	if (SX_SHARERS(sx->sx_lock) == 0)
+	/*
+	 * XXX: This can result in bogus behaviours since while we are
+	 * here a new shared owner can arrive and we are nomore the last
+	 * owner and the profile can be less accurate.  This operation,
+	 * really, should be atomic with the unlock operation but it can't
+	 * be, so there is not a safe way to do this.  At least it doesn't
+	 * hurt in this way.
+	 */
+	if (SX_SHARERS(sx->sx_lock) == 1)
 		lock_profile_release_lock(&sx->lock_object);
 	__sx_sunlock(sx, file, line);
 }
@@ -403,8 +411,6 @@
 			CTR2(KTR_LOCK, "%s: %p recursing", __func__, sx);
 		return;
 	}
-	lock_profile_obtain_lock_failed(&(sx)->lock_object,
-	    &contested, &waitstart);
 
 	if (LOCK_LOG_TEST(&sx->lock_object, 0))
 		CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
@@ -427,6 +433,8 @@
 					CTR3(KTR_LOCK,
 					    "%s: spinning on %p held by %p",
 					    __func__, sx, owner);
+				lock_profile_obtain_lock_failed(
+				    &sx->lock_object, &contested, &waitstart);
 				GIANT_SAVE();
 				while (SX_OWNER(sx->sx_lock) == x &&
 				    TD_IS_RUNNING(owner))
@@ -513,6 +521,8 @@
 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
 			    __func__, sx);
 
+		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
+		    &waitstart);
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
 		    SLEEPQ_SX, SQ_EXCLUSIVE_QUEUE);
@@ -522,7 +532,7 @@
 			CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
 			    __func__, sx);
 	}
-	
+
 	GIANT_RESTORE();
 	lock_profile_obtain_lock_success(&(sx)->lock_object, contested,
 	    waitstart, file, line);
@@ -613,20 +623,16 @@
 			MPASS(!(x & SX_LOCK_SHARED_WAITERS));
 			if (atomic_cmpset_acq_ptr(&sx->sx_lock, x,
 			    x + SX_ONE_SHARER)) {
-				if (SX_SHARERS(x) == 0)
-					lock_profile_obtain_lock_success(
-					    &sx->lock_object, contested,
-					    waitstart, file, line);
 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
 					CTR4(KTR_LOCK,
 					    "%s: %p succeed %p -> %p", __func__,
 					    sx, (void *)x,
 					    (void *)(x + SX_ONE_SHARER));
+				lock_profile_obtain_lock_success(
+				    &sx->lock_object, contested, waitstart,
+				    file, line);
 				break;
 			}
-			lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
-			    &waitstart);
-
 			continue;
 		}
 
@@ -640,12 +646,12 @@
 			x = SX_OWNER(x);
 			owner = (struct thread *)x;
 			if (TD_IS_RUNNING(owner)) {
-				lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
-				    &waitstart);
 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
 					CTR3(KTR_LOCK,
 					    "%s: spinning on %p held by %p",
 					    __func__, sx, owner);
+				lock_profile_obtain_lock_failed(
+				    &sx->lock_object, &contested, &waitstart);
 				GIANT_SAVE();
 				while (SX_OWNER(sx->sx_lock) == x &&
 				    TD_IS_RUNNING(owner))
@@ -654,9 +660,6 @@
 			}
 		} 
 #endif
-		else
-			lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
-			    &waitstart);
 
 		/*
 		 * Some other thread already has an exclusive lock, so
@@ -713,7 +716,9 @@
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
 			    __func__, sx);
-		
+
+		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
+		    &waitstart);
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
 		    SLEEPQ_SX, SQ_SHARED_QUEUE);
@@ -773,7 +778,6 @@
 			MPASS(x == SX_SHARERS_LOCK(1));
 			if (atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1),
 			    SX_LOCK_UNLOCKED)) {
-				lock_profile_release_lock(&sx->lock_object);
 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
 					CTR2(KTR_LOCK, "%s: %p last succeeded",
 					    __func__, sx);
@@ -788,7 +792,6 @@
 		 */
 		MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS));
 
-		lock_profile_release_lock(&sx->lock_object);
 		sleepq_lock(&sx->lock_object);
 
 		/*
--- /usr/src/sys/sys/sx.h	Wed Apr  4 18:50:30 2007
+++ sx.h	Wed Apr  4 19:08:26 2007
@@ -99,9 +99,9 @@
 	uintptr_t _tid = (uintptr_t)(tid);				\
 									\
 	if (!atomic_cmpset_acq_ptr(&(sx)->sx_lock, SX_LOCK_UNLOCKED,	\
-	    _tid)) {							\
+	    _tid))							\
 		_sx_xlock_hard((sx), _tid, (file), (line));		\
-	} else								\
+	else								\
 		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
 		    0, (file), (line));					\
 } while (0)
@@ -121,9 +121,9 @@
 									\
 	if (!(x & SX_LOCK_SHARED) ||					\
 	    !atomic_cmpset_acq_ptr(&(sx)->sx_lock, x,			\
-	    x + SX_ONE_SHARER)) {					\
+	    x + SX_ONE_SHARER))						\
 		_sx_slock_hard((sx), (file), (line));			\
-	} else								\
+	else								\
 		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
 		    0, (file), (line));					\
 } while (0)
