--- //depot/vendor/freebsd/src/sys/kern/kern_sx.c	2007/03/31 23:26:09
+++ //depot/user/attilio/attilio_smpng/kern/kern_sx.c	2007/04/02 19:53:58
@@ -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;
@@ -287,7 +292,8 @@
 	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);
+	if (!sx_recursed(sx))
+		lock_profile_release_lock(&sx->lock_object);
 	__sx_xunlock(sx, curthread, file, line);
 }
 
@@ -389,10 +395,15 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waitstart;
 	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 +415,8 @@
 		CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
 		    sx->lock_object.lo_name, (void *)sx->sx_lock, file, line);
 
+	waitstart = 0;
+	contested = 0;
 	while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) {
 #ifdef ADAPTIVE_SX
 		/*
@@ -421,6 +434,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))
@@ -507,6 +522,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);
@@ -518,6 +535,8 @@
 	}
 
 	GIANT_RESTORE();
+	lock_profile_obtain_lock_success(&sx->lock_object, contested, waitstart,
+	    file, line);
 }
 
 /*
@@ -584,12 +603,16 @@
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
+	uint64_t waitstart;
 	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.
 	 */
+	waitstart = 0;
+	contested = 0;
 	for (;;) {
 		x = sx->sx_lock;
 
@@ -603,6 +626,10 @@
 			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__,
@@ -627,6 +654,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))
@@ -692,6 +721,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_SHARED_QUEUE);
--- //depot/vendor/freebsd/src/sys/sys/sx.h	2007/03/31 23:26:09
+++ //depot/user/attilio/attilio_smpng/sys/sx.h	2007/04/02 19:53:58
@@ -97,17 +97,10 @@
 /* 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));					\
 } while (0)
 
 /* Release an exclusive lock. */
@@ -122,18 +115,11 @@
 /* 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));					\
 } while (0)
 
 /*
@@ -241,6 +227,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_*
