--- //depot/vendor/freebsd/src/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c	2005/12/12 01:05:49
+++ //depot/user/attilio/attilio_smpng/gnu/fs/xfs/FreeBSD/support/mrlock.c	2006/10/18 21:45:37
@@ -1,6 +1,7 @@
 #include <sys/param.h>
 #include <support/mrlock.h>
 
+#if 0
 void
 _sx_xfs_destroy(struct sx *sx)
 {
@@ -46,4 +47,4 @@
 }
 
 
-
+#endif
--- //depot/vendor/freebsd/src/sys/i386/include/param.h	2006/01/09 06:10:20
+++ //depot/user/attilio/attilio_smpng/i386/include/param.h	2006/10/03 21:33:06
@@ -109,6 +109,15 @@
 #endif
 
 /*
+ * Define our own cache alignment mask for syncronizing primitives.  Pentium4
+ * and Xeon want a 128-byte wide aligned syncronizing primitive in order to
+ * minimize cache bus traffic on CPUs cache lines movements.
+ */
+#ifndef	SYNC_ALIGN
+#define	SYNC_ALIGN	(128 - 1)
+#endif
+
+/*
  * Ceiling on size of buffer cache (really only effects write queueing,
  * the VM page cache is not effected), can be changed via
  * the kern.maxbcache /boot/loader.conf variable.
--- //depot/vendor/freebsd/src/sys/kern/kern_condvar.c	2006/02/23 00:15:20
+++ //depot/user/attilio/attilio_smpng/kern/kern_condvar.c	2006/10/07 01:15:11
@@ -149,7 +149,8 @@
 	DROP_GIANT();
 	mtx_unlock(mp);
 
-	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR);
+	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR,
+	    SQ_EXCLUSIVE_LOCK);
 	sleepq_wait(cvp);
 
 	PICKUP_GIANT();
@@ -197,7 +198,7 @@
 	mtx_unlock(mp);
 
 	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR |
-	    SLEEPQ_INTERRUPTIBLE);
+	    SLEEPQ_INTERRUPTIBLE, SQ_EXCLUSIVE_LOCK);
 	rval = sleepq_wait_sig(cvp);
 
 #ifdef KTRACE
@@ -250,7 +251,8 @@
 	DROP_GIANT();
 	mtx_unlock(mp);
 
-	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR);
+	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR,
+	    SQ_EXCLUSIVE_LOCK);
 	sleepq_set_timeout(cvp, timo);
 	rval = sleepq_timedwait(cvp);
 
@@ -308,7 +310,7 @@
 	mtx_unlock(mp);
 
 	sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR |
-	    SLEEPQ_INTERRUPTIBLE);
+	    SLEEPQ_INTERRUPTIBLE, SQ_EXCLUSIVE_LOCK);
 	sleepq_set_timeout(cvp, timo);
 	rval = sleepq_timedwait_sig(cvp);
 
@@ -337,7 +339,7 @@
 	sleepq_lock(cvp);
 	if (cvp->cv_waiters > 0) {
 		cvp->cv_waiters--;
-		sleepq_signal(cvp, SLEEPQ_CONDVAR, -1);
+		sleepq_signal(cvp, SLEEPQ_CONDVAR, -1, SQ_EXCLUSIVE_LOCK);
 	} else
 		sleepq_release(cvp);
 }
@@ -353,7 +355,7 @@
 	sleepq_lock(cvp);
 	if (cvp->cv_waiters > 0) {
 		cvp->cv_waiters = 0;
-		sleepq_broadcast(cvp, SLEEPQ_CONDVAR, pri);
+		sleepq_broadcast(cvp, SLEEPQ_CONDVAR, pri, SQ_EXCLUSIVE_LOCK);
 	} else
 		sleepq_release(cvp);
 }
--- //depot/vendor/freebsd/src/sys/kern/kern_ktrace.c	2006/10/22 11:58:01
+++ //depot/user/attilio/attilio_smpng/kern/kern_ktrace.c	2006/10/27 18:26:06
@@ -123,7 +123,6 @@
 
 static int print_message = 1;
 struct mtx ktrace_mtx;
-static struct cv ktrace_cv;
 static struct sx ktrace_sx;
 
 static void ktrace_init(void *dummy);
@@ -174,7 +173,6 @@
 
 	mtx_init(&ktrace_mtx, "ktrace", NULL, MTX_DEF | MTX_QUIET);
 	sx_init(&ktrace_sx, "ktrace_sx");
-	cv_init(&ktrace_cv, "ktrace");
 	STAILQ_INIT(&ktr_free);
 	for (i = 0; i < ktr_requestpool; i++) {
 		req = malloc(sizeof(struct ktr_request), M_KTRACE, M_WAITOK);
--- //depot/vendor/freebsd/src/sys/kern/kern_sx.c	2006/08/15 18:31:36
+++ //depot/user/attilio/attilio_smpng/kern/kern_sx.c	2006/10/18 21:57:08
@@ -1,30 +1,3 @@
-/*-
- * Copyright (C) 2001 Jason Evans <jasone@freebsd.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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice(s), this list of conditions and the following disclaimer as
- *    the first lines of this file unmodified other than the possible 
- *    addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice(s), this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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.
- */
-
 /*
  * Shared/exclusive locks.  This implementation assures deterministic lock
  * granting behavior, so that slocks and xlocks are interleaved.
@@ -33,24 +6,42 @@
  * so should not be relied upon in combination with sx locks.
  */
 
+/*
+ * The new implementation quite follows the rw locks semantic.
+ * Currently, we alredy use curthread in order to do an exclusive lock,
+ * but this is not really necessary; it could be used only for debugging
+ * purposes and for recursion avoidance (maybe it is better get rid of it).
+ * - We could introduce a sharers tracking for shared locks recursion detection
+ * - We MUST introduce adaptive spinning for s/xlocks.  BTW, a new patch is
+ *   under revision so maybe the current behaviour could change very soon.
+ *   This needs more speechs.
+ */
+#include "opt_ddb.h"
+
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_sx.c,v 1.30 2006/08/15 18:29:01 jhb Exp $");
 
-#include "opt_ddb.h"
-
 #include <sys/param.h>
-#include <sys/systm.h>
 #include <sys/ktr.h>
-#include <sys/linker_set.h>
-#include <sys/condvar.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/sleepqueue.h>
 #include <sys/sx.h>
+#include <sys/systm.h>
 
 #ifdef DDB
 #include <ddb/ddb.h>
+#endif
 
+#ifndef INVARIANTS
+#define	_sx_assert(sx, what, file, line)
+#endif
+
+#define	sx_xholder(sx)							\
+	(sx->sx_lock & SX_SHARED_BIT ? NULL :				\
+	(struct thread *)SX_HOLDER(sx->sx_lock))
+
+#ifdef DDB
 static void	db_show_sx(struct lock_object *lock);
 #endif
 
@@ -62,10 +53,6 @@
 #endif
 };
 
-#ifndef INVARIANTS
-#define	_sx_assert(sx, what, file, line)
-#endif
-
 void
 sx_sysinit(void *arg)
 {
@@ -78,13 +65,8 @@
 sx_init(struct sx *sx, const char *description)
 {
 
-	sx->sx_lock = mtx_pool_find(mtxpool_lockbuilder, sx);
-	sx->sx_cnt = 0;
-	cv_init(&sx->sx_shrd_cv, description);
-	sx->sx_shrd_wcnt = 0;
-	cv_init(&sx->sx_excl_cv, description);
-	sx->sx_excl_wcnt = 0;
-	sx->sx_xholder = NULL;
+	sx->sx_lock = SX_UNHELD;
+	sx->sx_desc = "sx lock";
 	lock_init(&sx->sx_object, &lock_class_sx, description, NULL,
 	    LO_WITNESS | LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE);
 }
@@ -93,225 +75,314 @@
 sx_destroy(struct sx *sx)
 {
 
-	KASSERT((sx->sx_cnt == 0 && sx->sx_shrd_wcnt == 0 && sx->sx_excl_wcnt ==
-	    0), ("%s (%s): holders or waiters\n", __func__,
-	    sx->sx_object.lo_name));
+	KASSERT(sx->sx_lock == SX_UNHELD, ("sx lock still held"));
+	lock_destroy(&sx->sx_object);
+}
+
+void
+_sx_xlock(struct sx *sx, const char *file, int line)
+{
+
+	MPASS(curthread != NULL);
+	MPASS(sx_xholder(sx) != curthread);
+	WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
+	    line);
+	__sx_xlock(sx, curthread, file, line);
+	LOCK_LOG_LOCK("XLOCK", &sx->sx_object, 0, 0, file, line);
+	WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
+	curthread->td_locks++;
+}
 
-	sx->sx_lock = NULL;
-	cv_destroy(&sx->sx_shrd_cv);
-	cv_destroy(&sx->sx_excl_cv);
+void
+_sx_xunlock(struct sx *sx, const char *file, int line)
+{
 
-	lock_destroy(&sx->sx_object);
+	MPASS(curthread != NULL);
+	_sx_assert(sx, SX_XLOCKED, file, line);
+	WITNESS_UNLOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
+	LOCK_LOG_LOCK("XUNLOCK", &sx->sx_object, 0, 0, file, line);
+	curthread->td_locks--;
+	__sx_xunlock(sx, curthread, file, line);
 }
 
 void
 _sx_slock(struct sx *sx, const char *file, int line)
 {
 
-	mtx_lock(sx->sx_lock);
-	KASSERT(sx->sx_xholder != curthread,
-	    ("%s (%s): slock while xlock is held @ %s:%d\n", __func__,
-	    sx->sx_object.lo_name, file, line));
+	MPASS(sx_xholder(sx) != curthread);
 	WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER, file, line);
+	__sx_slock(sx, file, line);
+	LOCK_LOG_LOCK("SLOCK", &sx->sx_object, 0, 0, file, line);
+	WITNESS_LOCK(&sx->sx_object, 0, file, line);
+	curthread->td_locks++;
+}
+
+void
+_sx_sunlock(struct sx *sx, const char *file, int line)
+{
 
-	/*
-	 * Loop in case we lose the race for lock acquisition.
-	 */
-	while (sx->sx_cnt < 0) {
-		sx->sx_shrd_wcnt++;
-		cv_wait(&sx->sx_shrd_cv, sx->sx_lock);
-		sx->sx_shrd_wcnt--;
-	}
+	_sx_assert(sx, SX_SLOCKED, file, line);
+	WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
+	LOCK_LOG_LOCK("SUNLOCK", &sx->sx_object, 0, 0, file, line);
+	curthread->td_locks--;
+	__sx_sunlock(sx, file, line);
+}
 
-	/* Acquire a shared lock. */
-	sx->sx_cnt++;
+int
+_sx_try_xlock(struct sx *sx, const char *file, int line)
+{
+	uintptr_t tid;
 
-	LOCK_LOG_LOCK("SLOCK", &sx->sx_object, 0, 0, file, line);
-	WITNESS_LOCK(&sx->sx_object, 0, file, line);
-	curthread->td_locks++;
+	MPASS(sx_xholder(sx) != curthread);
+	tid = (uintptr_t)curthread;
+	if (atomic_cmpset_acq_ptr(&sx->sx_lock, SX_UNHELD, tid)) {
+		LOCK_LOG_TRY("XLOCK", &sx->sx_object, 0, 1, file, line);
+		WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file,
+		    line);
+		curthread->td_locks++;
+		return (1);
+	}
 
-	mtx_unlock(sx->sx_lock);
+	LOCK_LOG_TRY("XLOCK", &sx->sx_object, 0, 0, file, line);
+	return (0);
 }
 
 int
 _sx_try_slock(struct sx *sx, const char *file, int line)
 {
+	uintptr_t x;
 
-	mtx_lock(sx->sx_lock);
-	if (sx->sx_cnt >= 0) {
-		sx->sx_cnt++;
+	MPASS(sx_xholder(sx) != curthread);
+	x = sx->sx_lock;
+	if ((x & SX_SHARED_BIT) && atomic_cmpset_acq_ptr(&sx->sx_lock, x,
+	    x + SX_ONE_SHARER)) {
 		LOCK_LOG_TRY("SLOCK", &sx->sx_object, 0, 1, file, line);
 		WITNESS_LOCK(&sx->sx_object, LOP_TRYLOCK, file, line);
 		curthread->td_locks++;
-		mtx_unlock(sx->sx_lock);
 		return (1);
-	} else {
-		LOCK_LOG_TRY("SLOCK", &sx->sx_object, 0, 0, file, line);
-		mtx_unlock(sx->sx_lock);
-		return (0);
 	}
+
+	LOCK_LOG_TRY("SLOCK", &sx->sx_object, 0, 0, file, line);
+	return (0);
 }
 
-void
-_sx_xlock(struct sx *sx, const char *file, int line)
+int
+_sx_try_upgrade(struct sx *sx, const char *file, int line)
 {
+	uintptr_t tid, x;
 
-	mtx_lock(sx->sx_lock);
+	_sx_assert(sx, SX_XLOCKED, file, line);
 
-	/*
-	 * With sx locks, we're absolutely not permitted to recurse on
-	 * xlocks, as it is fatal (deadlock). Normally, recursion is handled
-	 * by WITNESS, but as it is not semantically correct to hold the
-	 * xlock while in here, we consider it API abuse and put it under
-	 * INVARIANTS.
-	 */
-	KASSERT(sx->sx_xholder != curthread,
-	    ("%s (%s): xlock already held @ %s:%d", __func__,
-	    sx->sx_object.lo_name, file, line));
-	WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
-	    line);
+	tid = (uintptr_t)curthread;
+	if (!(sx->sx_lock & SX_EXCLUSIVE_WAITERS_BIT) &&
+	    atomic_cmpset_acq_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1), tid)) {
+		LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 1, file, line);
+		WITNESS_UPGRADE(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
+		    file, line);
+		return (1);
+	}
 
-	/* Loop in case we lose the race for lock acquisition. */
-	while (sx->sx_cnt != 0) {
-		sx->sx_excl_wcnt++;
-		cv_wait(&sx->sx_excl_cv, sx->sx_lock);
-		sx->sx_excl_wcnt--;
+	sleepq_lock(&sx->sx_object);
+	x = sx->sx_lock & SX_EXCLUSIVE_WAITERS_BIT;
+	if (atomic_cmpset_acq_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | x,
+	    tid | x)) {
+		sleepq_release(&sx->sx_object);
+		LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 1, file, line);
+		WITNESS_UPGRADE(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
+		    file, line);
+		return (1);
 	}
+	sleepq_release(&sx->sx_object);
 
-	MPASS(sx->sx_cnt == 0);
+	LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 0, file, line);
+	return (0);
+}
 
-	/* Acquire an exclusive lock. */
-	sx->sx_cnt--;
-	sx->sx_xholder = curthread;
+void
+_sx_downgrade(struct sx *sx, const char *file, int line)
+{
+	uintptr_t tid, x;
 
-	LOCK_LOG_LOCK("XLOCK", &sx->sx_object, 0, 0, file, line);
-	WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
-	curthread->td_locks++;
+	_sx_assert(sx, SX_XLOCKED, file, line);
+	WITNESS_DOWNGRADE(&sx->sx_object, 0, file, line);
 
-	mtx_unlock(sx->sx_lock);
-}
+	tid = (uintptr_t)curthread;
+	if (atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_SHARERS_LOCK(1))) {
+		LOCK_LOG_LOCK("XDOWNGRADE", &sx->sx_object, 0, 0, file, line);
+		return;
+	}
 
-int
-_sx_try_xlock(struct sx *sx, const char *file, int line)
-{
+	sleepq_lock(&sx->sx_object);
+	x = sx->sx_lock;
+	atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | (x &
+	    SX_EXCLUSIVE_WAITERS_BIT));
+	if (x & SX_SHARED_WAITERS_BIT)
+		sleepq_broadcast(&sx->sx_object, SLEEPQ_SX, -1,
+		    SQ_SHARED_QUEUE);
+	else
+		sleepq_release(&sx->sx_object);
 
-	mtx_lock(sx->sx_lock);
-	if (sx->sx_cnt == 0) {
-		sx->sx_cnt--;
-		sx->sx_xholder = curthread;
-		LOCK_LOG_TRY("XLOCK", &sx->sx_object, 0, 1, file, line);
-		WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file,
-		    line);
-		curthread->td_locks++;
-		mtx_unlock(sx->sx_lock);
-		return (1);
-	} else {
-		LOCK_LOG_TRY("XLOCK", &sx->sx_object, 0, 0, file, line);
-		mtx_unlock(sx->sx_lock);
-		return (0);
-	}
+	LOCK_LOG_LOCK("XDOWNGRADE", &sx->sx_object, 0, 0, file, line);
 }
 
 void
-_sx_sunlock(struct sx *sx, const char *file, int line)
+_sx_xlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
 {
+	uintptr_t x;
 
-	_sx_assert(sx, SX_SLOCKED, file, line);
-	mtx_lock(sx->sx_lock);
+	while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_UNHELD, tid)) {
+		sleepq_lock(&sx->sx_object);
+		x = sx->sx_lock;
+
+		if (x == SX_UNHELD) {
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
+
+		if (x == (SX_UNHELD | SX_EXCLUSIVE_WAITERS_BIT)) {
+			if (atomic_cmpset_acq_ptr(&sx->sx_lock, SX_UNHELD |
+			    SX_EXCLUSIVE_WAITERS_BIT, tid |
+			    SX_EXCLUSIVE_WAITERS_BIT)) {
+				sleepq_release(&sx->sx_object);
+				break;
+			}
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
 
-	curthread->td_locks--;
-	WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
+		if (!(x & SX_EXCLUSIVE_WAITERS_BIT) &&
+		    !atomic_cmpset_ptr(&sx->sx_lock, x, x |
+		    SX_EXCLUSIVE_WAITERS_BIT)) {
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
 
-	/* Release. */
-	sx->sx_cnt--;
+		if (LOCK_LOG_TEST(&sx->sx_object, 0))
+			CTR2(KTR_LOCK, "%s: %p blocking on sleepqueue",
+			    __func__, sx);
 
-	/*
-	 * If we just released the last shared lock, wake any waiters up, giving
-	 * exclusive lockers precedence.  In order to make sure that exclusive
-	 * lockers won't be blocked forever, don't wake shared lock waiters if
-	 * there are exclusive lock waiters.
-	 */
-	if (sx->sx_excl_wcnt > 0) {
-		if (sx->sx_cnt == 0)
-			cv_signal(&sx->sx_excl_cv);
-	} else if (sx->sx_shrd_wcnt > 0)
-		cv_broadcast(&sx->sx_shrd_cv);
+		DROP_GIANT();
+		sleepq_add(&sx->sx_object, NULL, sx->sx_desc, SLEEPQ_SX,
+		    SQ_EXCLUSIVE_QUEUE);
+		sleepq_wait(&sx->sx_object);
+		PICKUP_GIANT();
 
-	LOCK_LOG_LOCK("SUNLOCK", &sx->sx_object, 0, 0, file, line);
+		if (LOCK_LOG_TEST(&sx->sx_object, 0))
+			CTR2(KTR_LOCK, "%s: %p resuming from sleepqueue",
+			    __func__, sx);
+	}
 
-	mtx_unlock(sx->sx_lock);
 }
 
 void
-_sx_xunlock(struct sx *sx, const char *file, int line)
+_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
 {
+	uintptr_t x;
+	int queue;
 
-	_sx_assert(sx, SX_XLOCKED, file, line);
-	mtx_lock(sx->sx_lock);
-	MPASS(sx->sx_cnt == -1);
+	MPASS(sx->sx_lock & (SX_SHARED_WAITERS_BIT | SX_EXCLUSIVE_WAITERS_BIT));
+	MPASS(!(sx->sx_lock & SX_SHARED_BIT));
 
-	curthread->td_locks--;
-	WITNESS_UNLOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
+	sleepq_lock(&sx->sx_object);
+	x = SX_UNHELD;
+	if (sx->sx_lock & SX_SHARED_WAITERS_BIT) {
+		queue = SQ_SHARED_QUEUE;
+		x |= (sx->sx_lock & SX_EXCLUSIVE_WAITERS_BIT);
+	} else
+		queue = SQ_EXCLUSIVE_QUEUE;
+	if (LOCK_LOG_TEST(&sx->sx_object, 0))
+		CTR3(KTR_LOCK, "%s: %p waking up all thread on %s queue",
+		    __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
+		    "exclusive");
+	atomic_store_rel_ptr(&sx->sx_lock, x);
+	sleepq_broadcast(&sx->sx_object, SLEEPQ_SX, -1, queue);
+}
 
-	/* Release. */
-	sx->sx_cnt++;
-	sx->sx_xholder = NULL;
+void
+_sx_slock_hard(struct sx *sx, const char *file, int line)
+{
+	uintptr_t x;
 
-	/*
-	 * Wake up waiters if there are any.  Give precedence to slock waiters.
-	 */
-	if (sx->sx_shrd_wcnt > 0)
-		cv_broadcast(&sx->sx_shrd_cv);
-	else if (sx->sx_excl_wcnt > 0)
-		cv_signal(&sx->sx_excl_cv);
+	for (;;) {
+		x = sx->sx_lock;
+		if (x & SX_SHARED_BIT) {
+			MPASS(!(x & SX_SHARED_WAITERS_BIT));
+			if (atomic_cmpset_acq_ptr(&sx->sx_lock, x,
+			    x + SX_ONE_SHARER))
+				break;
+			continue;
+		}
 
-	LOCK_LOG_LOCK("XUNLOCK", &sx->sx_object, 0, 0, file, line);
+		sleepq_lock(&sx->sx_object);
+		x = sx->sx_lock;
 
-	mtx_unlock(sx->sx_lock);
-}
+		if (x & SX_SHARED_BIT) {
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
 
-int
-_sx_try_upgrade(struct sx *sx, const char *file, int line)
-{
+		if (!(x & SX_SHARED_WAITERS_BIT) &&
+		    !atomic_cmpset_ptr(&sx->sx_lock, x, x |
+		    SX_SHARED_WAITERS_BIT)) {
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
 
-	_sx_assert(sx, SX_SLOCKED, file, line);
-	mtx_lock(sx->sx_lock);
+		if (LOCK_LOG_TEST(&sx->sx_object, 0))
+			CTR2(KTR_LOCK, "%s: %p blocking on sleepqueue",
+			    __func__, sx);
 
-	if (sx->sx_cnt == 1) {
-		sx->sx_cnt = -1;
-		sx->sx_xholder = curthread;
+		DROP_GIANT();
+		sleepq_add(&sx->sx_object, NULL, sx->sx_desc, SLEEPQ_SX,
+		    SQ_SHARED_QUEUE);
+		sleepq_wait(&sx->sx_object);
+		PICKUP_GIANT();
 
-		LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 1, file, line);
-		WITNESS_UPGRADE(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
-		    file, line);
-
-		mtx_unlock(sx->sx_lock);
-		return (1);
-	} else {
-		LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 0, file, line);
-		mtx_unlock(sx->sx_lock);
-		return (0);
+		if (LOCK_LOG_TEST(&sx->sx_object, 0))
+			CTR2(KTR_LOCK, "%s: %p resuming from sleepqueue",
+			    __func__, sx);
 	}
 }
 
 void
-_sx_downgrade(struct sx *sx, const char *file, int line)
+_sx_sunlock_hard(struct sx *sx, const char *file, int line)
 {
+	uintptr_t x;
 
-	_sx_assert(sx, SX_XLOCKED, file, line);
-	mtx_lock(sx->sx_lock);
-	MPASS(sx->sx_cnt == -1);
+	for (;;) {
+		x = sx->sx_lock;
+		if (SX_SHARERS(x) > 1) {
+			if (atomic_cmpset_ptr(&sx->sx_lock, x,
+			    x - SX_ONE_SHARER))
+				break;
+			continue;
+		}
+
+		if (!(x & SX_EXCLUSIVE_WAITERS_BIT)) {
+			MPASS(x == SX_SHARERS_LOCK(1));
+			if (atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1),
+			    SX_UNHELD))
+				break;
+			continue;
+		}
 
-	WITNESS_DOWNGRADE(&sx->sx_object, 0, file, line);
+		MPASS(x == (SX_SHARERS_LOCK(1) | SX_EXCLUSIVE_WAITERS_BIT));
 
-	sx->sx_cnt = 1;
-	sx->sx_xholder = NULL;
-        if (sx->sx_shrd_wcnt > 0)
-                cv_broadcast(&sx->sx_shrd_cv);
+		sleepq_lock(&sx->sx_object);
+		if (!atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) |
+		    SX_EXCLUSIVE_WAITERS_BIT, SX_UNHELD)) {
+			sleepq_release(&sx->sx_object);
+			continue;
+		}
 
-	LOCK_LOG_LOCK("XDOWNGRADE", &sx->sx_object, 0, 0, file, line);
+		if (LOCK_LOG_TEST(&sx->sx_object, 0))
+			CTR2(KTR_LOCK, "%s: %p waking up all thread on"
+			    "exclusive queue", __func__, sx);
+		sleepq_broadcast(&sx->sx_object, SLEEPQ_SX, -1,
+		    SQ_EXCLUSIVE_QUEUE);
 
-	mtx_unlock(sx->sx_lock);
+		break;
+	}
 }
 
 #ifdef INVARIANT_SUPPORT
@@ -336,21 +407,18 @@
 #ifdef WITNESS
 		witness_assert(&sx->sx_object, what, file, line);
 #else
-		mtx_lock(sx->sx_lock);
-		if (sx->sx_cnt <= 0 &&
-		    (what == SX_SLOCKED || sx->sx_xholder != curthread))
+		if (sx->sx_lock == SX_UNHELD || (!(sx->sx_lock &
+		    SX_SHARED_BIT) && (what == RA_RLOCKED || sx_xholder(sx) !=
+		    curthread)))
 			panic("Lock %s not %slocked @ %s:%d\n",
 			    sx->sx_object.lo_name, (what == SX_SLOCKED) ?
 			    "share " : "", file, line);
-		mtx_unlock(sx->sx_lock);
 #endif
 		break;
 	case SX_XLOCKED:
-		mtx_lock(sx->sx_lock);
-		if (sx->sx_xholder != curthread)
+		if (sx_xholder(sx) != curthread)
 			panic("Lock %s not exclusively locked @ %s:%d\n",
 			    sx->sx_object.lo_name, file, line);
-		mtx_unlock(sx->sx_lock);
 		break;
 	case SX_UNLOCKED:
 #ifdef WITNESS
@@ -360,11 +428,9 @@
 		 * We are able to check only exclusive lock here,
 		 * we cannot assert that *this* thread owns slock.
 		 */
-		mtx_lock(sx->sx_lock);
-		if (sx->sx_xholder == curthread)
+		if (sx_xholder(sx) == curthread)
 			panic("Lock %s exclusively locked @ %s:%d\n",
 			    sx->sx_object.lo_name, file, line);
-		mtx_unlock(sx->sx_lock);
 #endif
 		break;
 	default:
@@ -375,76 +441,64 @@
 #endif	/* INVARIANT_SUPPORT */
 
 #ifdef DDB
-void
+static void
 db_show_sx(struct lock_object *lock)
 {
-	struct thread *td;
-	struct sx *sx;
+        struct thread *td;
+        struct sx *sx;
+
+        sx = (struct sx *)lock;
 
-	sx = (struct sx *)lock;
+	db_printf(" mask: 0x%x\n", sx->sx_lock);
+                   
+        db_printf(" state: ");
+        if (sx->sx_lock == SX_UNHELD)
+                db_printf("UNLOCKED\n");
+        else if (sx->sx_lock & SX_SHARED_BIT)
+                db_printf("SLOCK: %u\n", SX_SHARERS(sx->sx_lock));
+        else {
+                td = sx_xholder(sx);
+                db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
+                    td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
+        }
 
-	db_printf(" state: ");
-	if (sx->sx_cnt < 0) {
-		td = sx->sx_xholder;
-		db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
-		    td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
-	} else if (sx->sx_cnt > 0)
-		db_printf("SLOCK: %d locks\n", sx->sx_cnt);
-	else
-		db_printf("UNLOCKED\n");
-	db_printf(" waiters: %d shared, %d exclusive\n", sx->sx_shrd_wcnt,
-	    sx->sx_excl_wcnt);
+	db_printf(" waiters: ");
+	switch(sx->sx_lock & (SX_SHARED_WAITERS_BIT |
+	    SX_EXCLUSIVE_WAITERS_BIT)) {
+		case SX_EXCLUSIVE_WAITERS_BIT:
+			db_printf("shared\n");
+		break;
+		case SX_SHARED_WAITERS_BIT:
+			db_printf("exclusive\n");
+		break;
+		case SX_SHARED_WAITERS_BIT | SX_EXCLUSIVE_WAITERS_BIT:
+			db_printf("exclusive and shared\n");
+		break;
+		default:
+			db_printf("none\n");
+	}
 }
 
-/*
- * Check to see if a thread that is blocked on a sleep queue is actually
- * blocked on an sx lock.  If so, output some details and return true.
- * If the lock has an exclusive owner, return that in *ownerp.
- */
 int
 sx_chain(struct thread *td, struct thread **ownerp)
 {
 	struct sx *sx;
-	struct cv *cv;
+
+	sx = td->td_wchan;
 
-	/*
-	 * First, see if it looks like td is blocked on a condition
-	 * variable.
-	 */
-	cv = td->td_wchan;
-	if (cv->cv_description != td->td_wmesg)
+	if (sx->sx_desc != td->td_wmesg)
 		return (0);
 
-	/*
-	 * Ok, see if it looks like td is blocked on the exclusive
-	 * condition variable.
-	 */
-	sx = (struct sx *)((char *)cv - offsetof(struct sx, sx_excl_cv));
-	if (LOCK_CLASS(&sx->sx_object) == &lock_class_sx &&
-	    sx->sx_excl_wcnt > 0)
-		goto ok;
-
-	/*
-	 * Second, see if it looks like td is blocked on the shared
-	 * condition variable.
-	 */
-	sx = (struct sx *)((char *)cv - offsetof(struct sx, sx_shrd_cv));
-	if (LOCK_CLASS(&sx->sx_object) == &lock_class_sx &&
-	    sx->sx_shrd_wcnt > 0)
-		goto ok;
-
-	/* Doesn't seem to be an sx lock. */
-	return (0);
-
-ok:
-	/* We think we have an sx lock, so output some details. */
-	db_printf("blocked on sx \"%s\" ", td->td_wmesg);
-	if (sx->sx_cnt >= 0) {
-		db_printf("SLOCK (count %d)\n", sx->sx_cnt);
+	db_printf("blocked on sx lock");
+	if (sx->sx_lock == SX_UNHELD) {
+		db_printf("UNHELD\n");
+		*ownerp = NULL;
+	} else if (sx->sx_lock & SX_SHARED_BIT) {
+		db_printf("SHARED (count %u)\n", SX_SHARERS(sx->sx_lock));
 		*ownerp = NULL;
 	} else {
-		db_printf("XLOCK\n");
-		*ownerp = sx->sx_xholder;
+		db_printf("EXCL (holder: 0x%x)\n", SX_HOLDER(sx->sx_lock));
+		*ownerp = (struct thread *)SX_HOLDER(sx->sx_lock);
 	}
 	return (1);
 }
--- //depot/vendor/freebsd/src/sys/kern/kern_synch.c	2006/10/26 21:47:18
+++ //depot/user/attilio/attilio_smpng/kern/kern_synch.c	2006/10/27 18:26:06
@@ -188,7 +188,7 @@
 	 * stopped, then td will no longer be on a sleep queue upon
 	 * return from cursig().
 	 */
-	sleepq_add(ident, mtx, wmesg, flags);
+	sleepq_add(ident, mtx, wmesg, flags, SQ_EXCLUSIVE_LOCK);
 	if (timo)
 		sleepq_set_timeout(ident, timo);
 
@@ -265,7 +265,7 @@
 	/*
 	 * We put ourselves on the sleep queue and start our timeout.
 	 */
-	sleepq_add(ident, mtx, wmesg, SLEEPQ_MSLEEP);
+	sleepq_add(ident, mtx, wmesg, SLEEPQ_MSLEEP, SQ_EXCLUSIVE_LOCK);
 	if (timo)
 		sleepq_set_timeout(ident, timo);
 
@@ -314,7 +314,7 @@
 {
 
 	sleepq_lock(ident);
-	sleepq_broadcast(ident, SLEEPQ_MSLEEP, -1);
+	sleepq_broadcast(ident, SLEEPQ_MSLEEP, -1, SQ_EXCLUSIVE_LOCK);
 }
 
 /*
@@ -328,7 +328,7 @@
 {
 
 	sleepq_lock(ident);
-	sleepq_signal(ident, SLEEPQ_MSLEEP, -1);
+	sleepq_signal(ident, SLEEPQ_MSLEEP, -1, SQ_EXCLUSIVE_LOCK);
 }
 
 /*
--- //depot/vendor/freebsd/src/sys/kern/subr_sleepqueue.c	2006/04/21 20:47:06
+++ //depot/user/attilio/attilio_smpng/kern/subr_sleepqueue.c	2006/10/07 17:55:13
@@ -54,9 +54,7 @@
  * mix the sleep/wakeup and cv APIs for a given wait channel.  Also, one
  * must consistently use the same lock to synchronize with a wait channel,
  * though this check is currently only a warning for sleep/wakeup due to
- * pre-existing abuse of that API.  The same lock must also be held when
- * awakening threads, though that is currently only enforced for condition
- * variables.
+ * pre-existing abuse of that API.
  */
 
 #include <sys/cdefs.h>
@@ -70,7 +68,6 @@
 #include <sys/lock.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
-#include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/sched.h>
@@ -78,6 +75,8 @@
 #include <sys/sleepqueue.h>
 #include <sys/sysctl.h>
 
+#include <vm/uma.h>
+
 #ifdef DDB
 #include <ddb/ddb.h>
 #endif
@@ -96,6 +95,13 @@
 #define	SC_LOOKUP(wc)	&sleepq_chains[SC_HASH(wc)]
 
 /*
+ * Set the default item cache alignment if not specified otherwise.
+ */
+#ifndef	SYNC_ALIGN
+#define	SYNC_ALIGN	UMA_ALIGN_CACHE
+#endif
+
+/*
  * There two different lists of sleep queues.  Both lists are connected
  * via the sq_hash entries.  The first list is the sleep queue chain list
  * that a sleep queue is on when it is attached to a wait channel.  The
@@ -114,7 +120,7 @@
  *  c - sleep queue chain lock
  */
 struct sleepqueue {
-	TAILQ_HEAD(, thread) sq_blocked;	/* (c) Blocked threads. */
+	TAILQ_HEAD(, thread) sq_blocked[2];	/* (c) Blocked threads. */
 	LIST_ENTRY(sleepqueue) sq_hash;		/* (c) Chain and free list. */
 	LIST_HEAD(, sleepqueue) sq_free;	/* (c) Free queues. */
 	void	*sq_wchan;			/* (c) Wait channel. */
@@ -142,16 +148,20 @@
     0, "maxmimum depth achieved of a single chain");
 #endif
 static struct sleepqueue_chain sleepq_chains[SC_TABLESIZE];
-
-static MALLOC_DEFINE(M_SLEEPQUEUE, "sleepqueue", "sleep queues");
+static uma_zone_t sleepq_zone;
 
 /*
  * Prototypes for non-exported routines.
  */
+static int	sleepq_catch_signals(void *wchan);
+static int	sleepq_check_signals(void);
 static int	sleepq_check_timeout(void);
+static void	sleepq_fini(void *mem, int size);
+static int	sleepq_init(void *mem, int size, int flags);
+static void	sleepq_resume_thread(struct sleepqueue *sq, struct thread *td,
+		    int pri);
 static void	sleepq_switch(void *wchan);
 static void	sleepq_timeout(void *arg);
-static void	sleepq_resume_thread(struct sleepqueue *sq, struct thread *td, int pri);
 
 /*
  * Early initialization of sleep queues that is called from the sleepinit()
@@ -182,21 +192,19 @@
 		    NULL);
 #endif
 	}
+	sleepq_zone = uma_zcreate("SLEEPQUEUE", sizeof(struct sleepqueue),
+	    NULL, NULL, sleepq_init, sleepq_fini, SYNC_ALIGN, 0);
 	thread0.td_sleepqueue = sleepq_alloc();
 }
 
 /*
- * Malloc and initialize a new sleep queue for a new thread.
+ * Get a sleep queue for a new thread.
  */
 struct sleepqueue *
 sleepq_alloc(void)
 {
-	struct sleepqueue *sq;
 
-	sq = malloc(sizeof(struct sleepqueue), M_SLEEPQUEUE, M_WAITOK | M_ZERO);
-	TAILQ_INIT(&sq->sq_blocked);
-	LIST_INIT(&sq->sq_free);
-	return (sq);
+	return (uma_zalloc(sleepq_zone, M_WAITOK));
 }
 
 /*
@@ -206,9 +214,7 @@
 sleepq_free(struct sleepqueue *sq)
 {
 
-	MPASS(sq != NULL);
-	MPASS(TAILQ_EMPTY(&sq->sq_blocked));
-	free(sq, M_SLEEPQUEUE);
+	uma_zfree(sleepq_zone, sq);
 }
 
 /*
@@ -262,7 +268,8 @@
  * woken up.
  */
 void
-sleepq_add(void *wchan, struct mtx *lock, const char *wmesg, int flags)
+sleepq_add(void *wchan, struct mtx *lock, const char *wmesg, int flags,
+    int queue)
 {
 	struct sleepqueue_chain *sc;
 	struct sleepqueue *sq;
@@ -273,6 +280,7 @@
 	mtx_assert(&sc->sc_lock, MA_OWNED);
 	MPASS(td->td_sleepqueue != NULL);
 	MPASS(wchan != NULL);
+	MPASS(queue == SQ_EXCLUSIVE_QUEUE || queue == SQ_SHARED_QUEUE);
 
 	/* If this thread is not allowed to sleep, die a horrible death. */
 	KASSERT(!(td->td_pflags & TDP_NOSLEEPING),
@@ -297,8 +305,10 @@
 #endif
 		sq = td->td_sleepqueue;
 		LIST_INSERT_HEAD(&sc->sc_queues, sq, sq_hash);
-		KASSERT(TAILQ_EMPTY(&sq->sq_blocked),
-		    ("thread's sleep queue has a non-empty queue"));
+		KASSERT(TAILQ_EMPTY(&sq->sq_blocked[SQ_EXCLUSIVE_QUEUE]),
+		    ("thread's sleep queue has an exclusive non-empty queue"));
+		KASSERT(TAILQ_EMPTY(&sq->sq_blocked[SQ_SHARED_QUEUE]),
+		    ("thread's sleep queue has a shared non-empty queue"));
 		KASSERT(LIST_EMPTY(&sq->sq_free),
 		    ("thread's sleep queue has a non-empty free list"));
 		KASSERT(sq->sq_wchan == NULL, ("stale sq_wchan pointer"));
@@ -313,9 +323,10 @@
 		MPASS((flags & SLEEPQ_TYPE) == sq->sq_type);
 		LIST_INSERT_HEAD(&sq->sq_free, td->td_sleepqueue, sq_hash);
 	}
-	TAILQ_INSERT_TAIL(&sq->sq_blocked, td, td_slpq);
+	TAILQ_INSERT_TAIL(&sq->sq_blocked[queue], td, td_slpq);
 	td->td_sleepqueue = NULL;
 	mtx_lock_spin(&sched_lock);
+	td->td_sqqueue = queue;
 	td->td_wchan = wchan;
 	td->td_wmesg = wmesg;
 	if (flags & SLEEPQ_INTERRUPTIBLE) {
@@ -606,12 +617,14 @@
 	MPASS(td != NULL);
 	MPASS(sq->sq_wchan != NULL);
 	MPASS(td->td_wchan == sq->sq_wchan);
+	MPASS(td->td_sqqueue == SQ_EXCLUSIVE_QUEUE || td->td_sqqueue ==
+	    SQ_SHARED_QUEUE);
 	sc = SC_LOOKUP(sq->sq_wchan);
 	mtx_assert(&sc->sc_lock, MA_OWNED);
 	mtx_assert(&sched_lock, MA_OWNED);
 
 	/* Remove the thread from the queue. */
-	TAILQ_REMOVE(&sq->sq_blocked, td, td_slpq);
+	TAILQ_REMOVE(&sq->sq_blocked[td->td_sqqueue], td, td_slpq);
 
 	/*
 	 * Get a sleep queue for this thread.  If this is the last waiter,
@@ -653,16 +666,46 @@
 }
 
 /*
+ * UMA zone item deallocator.
+ */
+static void
+sleepq_fini(void *mem, int size)
+{
+	struct sleepqueue *sq;
+
+	sq = mem;
+	MPASS(TAILQ_EMPTY(&sq->sq_blocked[SQ_EXCLUSIVE_QUEUE]));
+	MPASS(TAILQ_EMPTY(&sq->sq_blocked[SQ_SHARED_QUEUE]));
+}
+
+/*
+ * UMA zone item initializer.
+ */
+static int
+sleepq_init(void *mem, int size, int flags)
+{
+	struct sleepqueue *sq;
+
+	bzero(mem, size);
+	sq = mem;
+	TAILQ_INIT(&sq->sq_blocked[SQ_EXCLUSIVE_QUEUE]);
+	TAILQ_INIT(&sq->sq_blocked[SQ_SHARED_QUEUE]);
+	LIST_INIT(&sq->sq_free);
+	return (0);
+}
+
+/*
  * Find the highest priority thread sleeping on a wait channel and resume it.
  */
 void
-sleepq_signal(void *wchan, int flags, int pri)
+sleepq_signal(void *wchan, int flags, int pri, int queue)
 {
 	struct sleepqueue *sq;
 	struct thread *td, *besttd;
 
 	CTR2(KTR_PROC, "sleepq_signal(%p, %d)", wchan, flags);
 	KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__));
+	MPASS(queue == SQ_EXCLUSIVE_QUEUE || queue == SQ_SHARED_QUEUE);
 	sq = sleepq_lookup(wchan);
 	if (sq == NULL) {
 		sleepq_release(wchan);
@@ -678,7 +721,7 @@
 	 * the tail of sleep queues.
 	 */
 	besttd = NULL;
-	TAILQ_FOREACH(td, &sq->sq_blocked, td_slpq) {
+	TAILQ_FOREACH(td, &sq->sq_blocked[queue], td_slpq) {
 		if (besttd == NULL || td->td_priority < besttd->td_priority)
 			besttd = td;
 	}
@@ -693,12 +736,13 @@
  * Resume all threads sleeping on a specified wait channel.
  */
 void
-sleepq_broadcast(void *wchan, int flags, int pri)
+sleepq_broadcast(void *wchan, int flags, int pri, int queue)
 {
 	struct sleepqueue *sq;
 
 	CTR2(KTR_PROC, "sleepq_broadcast(%p, %d)", wchan, flags);
 	KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__));
+	MPASS(queue == SQ_EXCLUSIVE_QUEUE || queue == SQ_SHARED_QUEUE);
 	sq = sleepq_lookup(wchan);
 	if (sq == NULL) {
 		sleepq_release(wchan);
@@ -709,8 +753,9 @@
 
 	/* Resume all blocked threads on the sleep queue. */
 	mtx_lock_spin(&sched_lock);
-	while (!TAILQ_EMPTY(&sq->sq_blocked))
-		sleepq_resume_thread(sq, TAILQ_FIRST(&sq->sq_blocked), pri);
+	while (!TAILQ_EMPTY(&sq->sq_blocked[queue]))
+		sleepq_resume_thread(sq, TAILQ_FIRST(&sq->sq_blocked[queue]),
+		    pri);
 	mtx_unlock_spin(&sched_lock);
 	sleepq_release(wchan);
 }
@@ -901,15 +946,27 @@
 	}
 #endif
 	db_printf("Blocked threads:\n");
-	if (TAILQ_EMPTY(&sq->sq_blocked))
+	db_printf("\nExclusive queue:\n");
+	if (TAILQ_EMPTY(&sq->sq_blocked[SQ_EXCLUSIVE_QUEUE]))
+		db_printf("\tempty\n");
+	else
+		TAILQ_FOREACH(td, &sq->sq_blocked[SQ_EXCLUSIVE_QUEUE],
+		    td_slpq) {
+			db_printf("\t%p (tid %d, pid %d, \"%s\")\n", td,
+			    td->td_tid, td->td_proc->p_pid,
+			    td->td_name[0] != '\0' ? td->td_name :
+			    td->td_proc->p_comm);
+		}
+	db_printf("\nShared queue:\n");
+	if (TAILQ_EMPTY(&sq->sq_blocked[SQ_SHARED_QUEUE]))
 		db_printf("\tempty\n");
 	else
-		TAILQ_FOREACH(td, &sq->sq_blocked, td_slpq) {
+		TAILQ_FOREACH(td, &sq->sq_blocked[SQ_SHARED_QUEUE], td_slpq) {
 			db_printf("\t%p (tid %d, pid %d, \"%s\")\n", td,
 			    td->td_tid, td->td_proc->p_pid,
 			    td->td_name[0] != '\0' ? td->td_name :
 			    td->td_proc->p_comm);
-		}	
+		}
 }
 
 /* Alias 'show sleepqueue' to 'show sleepq'. */
--- //depot/vendor/freebsd/src/sys/kern/subr_turnstile.c	2006/08/15 18:31:36
+++ //depot/user/attilio/attilio_smpng/kern/subr_turnstile.c	2006/10/03 21:33:06
@@ -46,14 +46,14 @@
  * chain.  Each chain contains a spin mutex that protects all of the
  * turnstiles in the chain.
  *
- * Each time a thread is created, a turnstile is malloc'd and attached to
- * that thread.  When a thread blocks on a lock, if it is the first thread
- * to block, it lends its turnstile to the lock.  If the lock already has
- * a turnstile, then it gives its turnstile to the lock's turnstile's free
- * list.  When a thread is woken up, it takes a turnstile from the free list
- * if there are any other waiters.  If it is the only thread blocked on the
- * lock, then it reclaims the turnstile associated with the lock and removes
- * it from the hash table.
+ * Each time a thread is created, a turnstile is got from a specific UMA zone
+ * and attached to that thread.  When a thread blocks on a lock, if it is the
+ * first thread to block, it lends its turnstile to the lock.  If the lock
+ * already has a turnstile, then it gives its turnstile to the lock's
+ * turnstile's free list.  When a thread is woken up, it takes a turnstile from
+ * the free list if there are any other waiters.  If it is the only thread
+ * blocked on the lock, then it reclaims the turnstile associated with the lock
+ * and removes it from the hash table.
  */
 
 #include <sys/cdefs.h>
@@ -67,7 +67,6 @@
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
-#include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
@@ -75,6 +74,8 @@
 #include <sys/sysctl.h>
 #include <sys/turnstile.h>
 
+#include <vm/uma.h>
+
 #ifdef DDB
 #include <sys/kdb.h>
 #include <ddb/ddb.h>
@@ -95,6 +96,13 @@
 #define	TC_LOOKUP(lock)	&turnstile_chains[TC_HASH(lock)]
 
 /*
+ * Set the default item cache alignment if not specified otherwise.
+ */
+#ifndef	SYNC_ALIGN
+#define	SYNC_ALIGN	UMA_ALIGN_CACHE
+#endif
+
+/*
  * There are three different lists of turnstiles as follows.  The list
  * connected by ts_link entries is a per-thread list of all the turnstiles
  * attached to locks that we own.  This is used to fixup our priority when
@@ -143,8 +151,7 @@
 #endif
 static struct mtx td_contested_lock;
 static struct turnstile_chain turnstile_chains[TC_TABLESIZE];
-
-static MALLOC_DEFINE(M_TURNSTILE, "turnstiles", "turnstiles");
+static uma_zone_t turnstile_zone;
 
 /*
  * Prototypes for non-exported routines.
@@ -158,6 +165,8 @@
 		    struct thread *td);
 static struct thread *turnstile_first_waiter(struct turnstile *ts);
 static void	turnstile_setowner(struct turnstile *ts, struct thread *owner);
+static void	turnstile_fini(void *mem, int size);
+static int	turnstile_init(void *mem, int size, int flags);
 
 /*
  * Walks the chain of turnstiles and their owners to propagate the priority
@@ -379,6 +388,8 @@
 init_turnstile0(void *dummy)
 {
 
+	turnstile_zone = uma_zcreate("TURNSTILE", sizeof(struct turnstile),
+	    NULL, NULL, turnstile_init, turnstile_fini, SYNC_ALIGN, 0);
 	thread0.td_turnstile = turnstile_alloc();
 }
 SYSINIT(turnstile0, SI_SUB_LOCK, SI_ORDER_ANY, init_turnstile0, NULL);
@@ -446,19 +457,44 @@
 }
 
 /*
- * Malloc a turnstile for a new thread, initialize it and return it.
+ * UMA zone item deallocator.
+ */
+static void
+turnstile_fini(void *mem, int size)
+{
+	struct turnstile *ts;
+
+	ts = mem;
+	MPASS(TAILQ_EMPTY(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]));
+	MPASS(TAILQ_EMPTY(&ts->ts_blocked[TS_SHARED_QUEUE]));
+	MPASS(TAILQ_EMPTY(&ts->ts_pending));
+}
+
+/*
+ * UMA zone item initializer.
  */
-struct turnstile *
-turnstile_alloc(void)
+static int
+turnstile_init(void *mem, int size, int flags)
 {
 	struct turnstile *ts;
 
-	ts = malloc(sizeof(struct turnstile), M_TURNSTILE, M_WAITOK | M_ZERO);
+	bzero(mem, size);
+	ts = mem;
 	TAILQ_INIT(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]);
 	TAILQ_INIT(&ts->ts_blocked[TS_SHARED_QUEUE]);
 	TAILQ_INIT(&ts->ts_pending);
 	LIST_INIT(&ts->ts_free);
-	return (ts);
+	return (0);
+}
+
+/*
+ * Get a turnstile for a new thread.
+ */
+struct turnstile *
+turnstile_alloc(void)
+{
+
+	return (uma_zalloc(turnstile_zone, M_WAITOK));
 }
 
 /*
@@ -468,11 +504,7 @@
 turnstile_free(struct turnstile *ts)
 {
 
-	MPASS(ts != NULL);
-	MPASS(TAILQ_EMPTY(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]));
-	MPASS(TAILQ_EMPTY(&ts->ts_blocked[TS_SHARED_QUEUE]));
-	MPASS(TAILQ_EMPTY(&ts->ts_pending));
-	free(ts, M_TURNSTILE);
+	uma_zfree(turnstile_zone, ts);
 }
 
 /*
--- //depot/vendor/freebsd/src/sys/sys/proc.h	2006/10/27 05:46:50
+++ //depot/user/attilio/attilio_smpng/sys/proc.h	2006/10/27 18:26:06
@@ -294,6 +294,7 @@
 	int		td_inhibitors;	/* (j) Why can not run. */
 	int		td_pflags;	/* (k) Private thread (TDP_*) flags. */
 	int		td_dupfd;	/* (k) Ret value from fdopen. XXX */
+	int		td_sqqueue;	/* (j) Sleep queue blocked on. */
 	void		*td_wchan;	/* (j) Sleep address. */
 	const char	*td_wmesg;	/* (j) Reason for sleep. */
 	u_char		td_lastcpu;	/* (j) Last cpu we were on. */
--- //depot/vendor/freebsd/src/sys/sys/sleepqueue.h	2006/02/15 23:55:18
+++ //depot/user/attilio/attilio_smpng/sys/sleepqueue.h	2006/10/10 12:47:59
@@ -33,8 +33,8 @@
 #define _SYS_SLEEPQUEUE_H_
 
 /*
- * Sleep queue interface.  Sleep/wakeup and condition variables use a sleep
- * queue for the queue of threads blocked on a sleep channel.
+ * Sleep queue interface.  Sleep/wakeup, condition variables and sx locks
+ * use a sleep queue for the queue of threads blocked on a sleep channel.
  *
  * A thread calls sleepq_lock() to lock the sleep queue chain associated
  * with a given wait channel.  A thread can then call call sleepq_add() to
@@ -84,23 +84,29 @@
 #define	SLEEPQ_TYPE		0x0ff		/* Mask of sleep queue types. */
 #define	SLEEPQ_MSLEEP		0x00		/* Used by msleep/wakeup. */
 #define	SLEEPQ_CONDVAR		0x01		/* Used for a cv. */
+#define	SLEEPQ_SX		0x02		/* Used for a sx lock. */
 #define	SLEEPQ_INTERRUPTIBLE	0x100		/* Sleep is interruptible. */
 
+/* Handy sleep queues delivery constants. */
+#define	SQ_EXCLUSIVE_QUEUE	0
+#define	SQ_SHARED_QUEUE		1
+
 void	init_sleepqueues(void);
 void	sleepq_abort(struct thread *td, int intrval);
-void	sleepq_add(void *, struct mtx *, const char *, int);
+void	sleepq_add(void *wchan, struct mtx *lock, const char *wmesg, int flags,
+	    int queue);
 struct sleepqueue *sleepq_alloc(void);
-void	sleepq_broadcast(void *, int, int);
-void	sleepq_free(struct sleepqueue *);
-void	sleepq_lock(void *);
-struct sleepqueue *sleepq_lookup(void *);
-void	sleepq_release(void *);
-void	sleepq_remove(struct thread *, void *);
-void	sleepq_signal(void *, int, int);
+void	sleepq_broadcast(void *wchan, int flags, int pri, int queue);
+void	sleepq_free(struct sleepqueue *sq);
+void	sleepq_lock(void *wchan);
+struct sleepqueue *sleepq_lookup(void *wchan);
+void	sleepq_release(void *wchan);
+void	sleepq_remove(struct thread *td, void *wchan);
+void	sleepq_signal(void *wchan, int flags, int pri, int queue);
 void	sleepq_set_timeout(void *wchan, int timo);
 int	sleepq_timedwait(void *wchan);
 int	sleepq_timedwait_sig(void *wchan);
-void	sleepq_wait(void *);
+void	sleepq_wait(void *wchan);
 int	sleepq_wait_sig(void *wchan);
 
 #endif	/* _KERNEL */
--- //depot/vendor/freebsd/src/sys/sys/sx.h	2006/08/29 20:39:49
+++ //depot/user/attilio/attilio_smpng/sys/sx.h	2006/10/18 21:57:08
@@ -1,51 +1,70 @@
-/*-
- * Copyright (C) 2001 Jason Evans <jasone@freebsd.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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice(s), this list of conditions and the following disclaimer as
- *    the first lines of this file unmodified other than the possible 
- *    addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice(s), this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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.
- *
- * $FreeBSD: src/sys/sys/sx.h,v 1.26 2006/08/29 20:36:33 jhb Exp $
- */
-
 #ifndef	_SYS_SX_H_
 #define	_SYS_SX_H_
 
-#include <sys/queue.h>
 #include <sys/_lock.h>
-#include <sys/condvar.h>	/* XXX */
+#include <sys/_sx.h>
+
+#ifdef	_KERNEL
+#include <machine/atomic.h>
+#endif
+
+#define	SX_SHARED_BIT			0x01
+#define	SX_SHARED_WAITERS_BIT		0x02
+#define	SX_EXCLUSIVE_WAITERS_BIT	0x04
+#define	SX_FLAGMASK							\
+	(SX_SHARED_BIT | SX_SHARED_WAITERS_BIT | SX_EXCLUSIVE_WAITERS_BIT)
 
-struct sx {
-	struct lock_object sx_object;	/* Common lock properties. */
-	struct mtx	*sx_lock;	/* General protection lock. */
-	int		sx_cnt;		/* -1: xlock, > 0: slock count. */
-	struct cv	sx_shrd_cv;	/* slock waiters. */
-	int		sx_shrd_wcnt;	/* Number of slock waiters. */
-	struct cv	sx_excl_cv;	/* xlock waiters. */
-	int		sx_excl_wcnt;	/* Number of xlock waiters. */
-	struct thread	*sx_xholder;	/* Thread presently holding xlock. */
-};
+#define	SX_HOLDER(x)			((x) & ~SX_FLAGMASK)
+#define	SX_SHARERS_SHIFT		3
+#define	SX_SHARERS(x)			(SX_HOLDER(x) >> SX_SHARERS_SHIFT)
+#define	SX_SHARERS_LOCK(x)		((x) << SX_SHARERS_SHIFT |	\
+					SX_SHARED_BIT)
+#define	SX_ONE_SHARER			(1 << SX_SHARERS_SHIFT)
+#define	SX_UNHELD			SX_SHARERS_LOCK(0)
 
 #ifdef _KERNEL
+#define	__sx_xlock(sx, tid, file, line) do {				\
+		uintptr_t _tid = (uintptr_t)(tid);			\
+									\
+		if (!atomic_cmpset_acq_ptr(&(sx)->sx_lock, SX_UNHELD,	\
+		    _tid))						\
+			_sx_xlock_hard((sx), _tid, (file), (line));	\
+} while (0)
+
+#define	__sx_xunlock(sx, tid, file, line) do {				\
+		uintptr_t _tid = (uintptr_t)(tid);			\
+									\
+		if (!atomic_cmpset_rel_ptr(&(sx)->sx_lock, _tid,	\
+		    SX_UNHELD))						\
+			_sx_xunlock_hard((sx), _tid, (file), (line));	\
+} while (0)
+
+#define	__sx_slock(sx, file, line) do {					\
+		uintptr_t x = ((struct sx *)(sx))->sx_lock;		\
+									\
+		if (x & SX_SHARED_BIT) {				\
+			if (!atomic_cmpset_acq_ptr(&(sx)->sx_lock, x,	\
+			    x + SX_ONE_SHARER))				\
+				_sx_slock_hard((sx), (file), (line));	\
+		} else							\
+			_sx_slock_hard((sx), (file), (line));		\
+} while (0)
+
+#define	__sx_sunlock(sx, file, line) do {				\
+		uintptr_t x = ((struct sx *)(sx))->sx_lock;		\
+									\
+		if (SX_SHARERS(x) > 1) {				\
+			if (!atomic_cmpset_ptr(&(sx)->sx_lock, x,	\
+			    x - SX_ONE_SHARER))				\
+				_sx_sunlock_hard((sx), (file), (line));	\
+		} else if (!(x & SX_EXCLUSIVE_WAITERS_BIT)) {		\
+			if(!atomic_cmpset_ptr(&(sx)->sx_lock,		\
+			    SX_SHARERS_LOCK(1), SX_UNHELD))		\
+				_sx_sunlock_hard((sx), (file), (line));	\
+		} else							\
+			_sx_sunlock_hard((sx), (file), (line));		\
+} while (0)
+
 void	sx_sysinit(void *arg);
 void	sx_init(struct sx *sx, const char *description);
 void	sx_destroy(struct sx *sx);
@@ -57,6 +76,12 @@
 void	_sx_xunlock(struct sx *sx, const char *file, int line);
 int	_sx_try_upgrade(struct sx *sx, const char *file, int line);
 void	_sx_downgrade(struct sx *sx, const char *file, int line);
+void	_sx_xlock_hard(struct sx *sx, uintptr_t tid, const char *file, int
+	    line);
+void	_sx_slock_hard(struct sx *sx, const char *file, int line);
+void	_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int
+	    line);
+void	_sx_sunlock_hard(struct sx *sx, const char *file, int line);
 #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
 void	_sx_assert(struct sx *sx, int what, const char *file, int line);
 #endif
@@ -79,7 +104,6 @@
 	SYSUNINIT(name##_sx_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE,	\
 	    sx_destroy, (sxa))
 
-#define	sx_xlocked(sx)		((sx)->sx_cnt < 0 && (sx)->sx_xholder == curthread)
 #define	sx_slock(sx)		_sx_slock((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_xlock(sx)		_sx_xlock((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_try_slock(sx)	_sx_try_slock((sx), LOCK_FILE, LOCK_LINE)
@@ -88,6 +112,10 @@
 #define	sx_xunlock(sx)		_sx_xunlock((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_try_upgrade(sx)	_sx_try_upgrade((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_downgrade(sx)	_sx_downgrade((sx), LOCK_FILE, LOCK_LINE)
+
+#define	sx_xlocked(sx)							\
+	(SX_HOLDER((sx)->sx_lock) == (uintptr_t)curthread)
+
 #define	sx_unlock(sx) do {						\
 	if (sx_xlocked(sx))						\
 		sx_xunlock(sx);						\
