--- //depot/vendor/freebsd/src/sys/kern/kern_sx.c	2007/04/04 00:02:34
+++ //depot/user/attilio/attilio_smpng/kern/kern_sx.c	2007/04/04 00:04:14
@@ -40,7 +40,7 @@
 #include "opt_ddb.h"
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_sx.c,v 1.42 2007/04/04 00:01:05 kmacy Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_sx.c,v 1.40 2007/03/31 23:23:42 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/ktr.h>
@@ -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,8 +273,6 @@
 	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(x) == 0)
-		lock_profile_release_lock(&sx->lock_object);
 	__sx_sunlock(sx, file, line);
 }
 
@@ -391,9 +389,9 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waittime = 0;
 	uintptr_t x;
 	int contested = 0;
-	uint64_t waitstart = 0;
 
 	/* If we already hold an exclusive lock, then recurse. */
 	if (sx_xlocked(sx)) {
@@ -403,8 +401,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 +423,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))
@@ -513,6 +511,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);
@@ -522,10 +522,10 @@
 			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);
+	lock_profile_obtain_lock_success(&sx->lock_object, contested, waittime,
+	    file, line);
 }
 
 /*
@@ -592,14 +592,14 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waittime = 0;
 	uintptr_t x;
-	uint64_t waitstart = 0;
 	int contested = 0;
+
 	/*
 	 * As with rwlocks, we don't make any attempt to try to block
 	 * shared locks once there is an exclusive waiter.
 	 */
-	
 	for (;;) {
 		x = sx->sx_lock;
 
@@ -613,20 +613,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, waittime,
+				    file, line);
 				break;
 			}
-			lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
-			    &waitstart);
-
 			continue;
 		}
 
@@ -640,23 +636,20 @@
 			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, &waittime);
 				GIANT_SAVE();
 				while (SX_OWNER(sx->sx_lock) == x &&
 				    TD_IS_RUNNING(owner))
 					cpu_spinwait();
 				continue;
 			}
-		} 
+		}
 #endif
-		else
-			lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
-			    &waitstart);
 
 		/*
 		 * Some other thread already has an exclusive lock, so
@@ -713,7 +706,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,
+		    &waittime);
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
 		    SLEEPQ_SX, SQ_SHARED_QUEUE);
@@ -766,6 +761,13 @@
 		}
 
 		/*
+		 * This stub here is bogus since a new shared owner can arrive
+		 * and let the loop restart.  However, there is not an easy
+		 * way to fix it, so does the less hurting thing.
+		 */
+		lock_profile_release_lock(&sx->lock_object);
+
+		/*
 		 * If there aren't any waiters for an exclusive lock,
 		 * then try to drop it quickly.
 		 */
@@ -773,7 +775,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 +789,6 @@
 		 */
 		MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS));
 
-		lock_profile_release_lock(&sx->lock_object);
 		sleepq_lock(&sx->lock_object);
 
 		/*
--- //depot/vendor/freebsd/src/sys/sys/sx.h	2007/04/03 23:02:12
+++ //depot/user/attilio/attilio_smpng/sys/sx.h	2007/04/04 00:04:14
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * $FreeBSD: src/sys/sys/sx.h,v 1.30 2007/04/03 22:58:21 kmacy Exp $
+ * $FreeBSD: src/sys/sys/sx.h,v 1.29 2007/03/31 23:23:42 jhb Exp $
  */
 
 #ifndef	_SYS_SX_H_
@@ -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)
