--- //depot/vendor/freebsd/src/sys/i386/i386/sys_machdep.c	2007/05/29 18:57:33
+++ //depot/user/attilio/attilio_smpng/i386/i386/sys_machdep.c	2007/06/21 10:31:38
@@ -42,7 +42,6 @@
 #include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
-#include <sys/refcount.h>
 #include <sys/smp.h>
 #include <sys/sysproto.h>
 
@@ -66,14 +65,20 @@
 #define NEW_MAX_LD(num)  ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1))
 #define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3)
 
+#ifdef SMP
+#define	NULL_LDT_BASE	((caddr_t)NULL)
 
+struct sulrv {
+	struct mdproc	*mdp;
+	caddr_t		oldt;
+};
 
+static void set_user_ldt_rv(struct sulrv *srv);
+#endif
+
 static int i386_set_ldt_data(struct thread *, int start, int num,
 	union descriptor *descs);
 static int i386_ldt_grow(struct thread *td, int len);
-#ifdef SMP
-static void set_user_ldt_rv(struct thread *);
-#endif
 
 #ifndef _SYS_SYSPROTO_H_
 struct sysarch_args {
@@ -378,13 +383,15 @@
 
 #ifdef SMP
 static void
-set_user_ldt_rv(struct thread *td)
+set_user_ldt_rv(struct sulrv *srv)
 {
+	struct proc_ldt *pldt;
 
-	if (td->td_proc != curthread->td_proc)
+	pldt = curthread->td_proc->p_md.md_ldt;
+	if (pldt == NULL || srv->oldt != pldt->ldt_base)
 		return;
 
-	set_user_ldt(&td->td_proc->p_md);
+	set_user_ldt(srv->mdp);
 }
 #endif
 
@@ -408,7 +415,7 @@
 		FREE(new_ldt, M_SUBPROC);
 		return NULL;
 	}
-	refcount_init(&new_ldt->ldt_refcnt, 1);
+	new_ldt->ldt_refcnt = 1;
 	new_ldt->ldt_active = 0;
 
 	mtx_lock_spin(&dt_lock);
@@ -446,12 +453,13 @@
 	}
 
 	mdp->md_ldt = NULL;
-	mtx_unlock_spin(&dt_lock);
-	if (refcount_release(&pldt->ldt_refcnt)) {
+	if (--pldt->ldt_refcnt == 0) {
+		mtx_unlock_spin(&dt_lock);
 		kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
 			pldt->ldt_len * sizeof(union descriptor));
 		FREE(pldt, M_SUBPROC);
-	}
+	} else
+		mtx_unlock_spin(&dt_lock);
 }
 
 /*
@@ -689,10 +697,13 @@
 static int
 i386_ldt_grow(struct thread *td, int len) 
 {
+#ifdef SMP
+	struct sulrv tmpsrv;
+#endif
 	struct mdproc *mdp = &td->td_proc->p_md;
-	struct proc_ldt *pldt;
-	caddr_t old_ldt_base;
-	int old_ldt_len;
+	struct proc_ldt *new_ldt, *pldt;
+	caddr_t old_ldt_base = NULL_LDT_BASE;
+	int old_ldt_len = 0;
 
 	mtx_assert(&dt_lock, MA_OWNED);
 
@@ -703,29 +714,16 @@
 
 	/* Allocate a user ldt. */
 	if ((pldt = mdp->md_ldt) == NULL || len > pldt->ldt_len) {
-		struct proc_ldt *new_ldt;
-
 		new_ldt = user_ldt_alloc(mdp, len);
 		if (new_ldt == NULL)
 			return (ENOMEM);
 		pldt = mdp->md_ldt;
 
 		if (pldt != NULL) {
-			if (new_ldt->ldt_len > pldt->ldt_len) {
-				old_ldt_base = pldt->ldt_base;
-				old_ldt_len = pldt->ldt_len;
-				pldt->ldt_sd = new_ldt->ldt_sd;
-				pldt->ldt_base = new_ldt->ldt_base;
-				pldt->ldt_len = new_ldt->ldt_len;
-				mtx_unlock_spin(&dt_lock);
-				kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
-					old_ldt_len * sizeof(union descriptor));
-				FREE(new_ldt, M_SUBPROC);
-				mtx_lock_spin(&dt_lock);
-			} else {
+			if (new_ldt->ldt_len <= pldt->ldt_len) {
 				/*
-				 * If other threads already did the work,
-				 * do nothing.
+				 * We just lost the race for allocation, so
+				 * free the new object and return.
 				 */
 				mtx_unlock_spin(&dt_lock);
 				kmem_free(kernel_map,
@@ -735,6 +733,16 @@
 				mtx_lock_spin(&dt_lock);
 				return (0);
 			}
+
+			/*
+			 * We have to substitute the current LDT entry for
+			 * curproc with the new one since its size grew up.
+			 */
+			old_ldt_base = pldt->ldt_base;
+			old_ldt_len = pldt->ldt_len;
+			pldt->ldt_sd = new_ldt->ldt_sd;
+			pldt->ldt_base = new_ldt->ldt_base;
+			pldt->ldt_len = new_ldt->ldt_len;
 		} else
 			mdp->md_ldt = pldt = new_ldt;
 #ifdef SMP
@@ -745,11 +753,25 @@
 		 * to acquire it.
 		 */
 		mtx_unlock_spin(&dt_lock);
+		tmpsrv.mdp = mdp;
+		tmpsrv.oldt = old_ldt_base;
 		smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
-		    NULL, td);
+		    NULL, &tmpsrv);
+		if (old_ldt_base != NULL_LDT_BASE) {
+#else
+		set_user_ldt(mdp);
+		if (old_ldt_base != NULL_LDT_BASE) {
+			mtx_unlock_spin(&dt_lock);
+#endif
+			kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
+			    old_ldt_len * sizeof(union descriptor));
+			FREE(new_ldt, M_SUBPROC);
+#ifdef SMP
+		}
 		mtx_lock_spin(&dt_lock);
 #else
-		set_user_ldt(mdp);
+			mtx_lock_spin(&dt_lock);
+		}
 #endif
 	}
 	return (0);
--- //depot/vendor/freebsd/src/sys/i386/i386/vm_machdep.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_smpng/i386/i386/vm_machdep.c	2007/06/21 08:57:03
@@ -62,7 +62,6 @@
 #include <sys/mutex.h>
 #include <sys/pioctl.h>
 #include <sys/proc.h>
-#include <sys/refcount.h>
 #include <sys/sf_buf.h>
 #include <sys/smp.h>
 #include <sys/sched.h>
@@ -254,7 +253,7 @@
 	mtx_lock_spin(&dt_lock);
 	if (mdp2->md_ldt != NULL) {
 		if (flags & RFMEM) {
-			refcount_acquire(&mdp2->md_ldt->ldt_refcnt);
+			mdp2->md_ldt->ldt_refcnt++;
 		} else {
 			mdp2->md_ldt = user_ldt_alloc(mdp2,
 			    mdp2->md_ldt->ldt_len);
--- //depot/vendor/freebsd/src/sys/i386/linux/linux_machdep.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_smpng/i386/linux/linux_machdep.c	2007/06/07 21:32:30
@@ -847,9 +847,7 @@
 	iia.start = args->start;
 	iia.length = args->length;
 	iia.enable = args->enable;
-	mtx_lock(&Giant);
 	error = i386_set_ioperm(td, &iia);
-	mtx_unlock(&Giant);
 	return (error);
 }
 
@@ -885,10 +883,8 @@
 		ldt.start = 0;
 		ldt.descs = uap->ptr;
 		ldt.num = uap->bytecount / sizeof(union descriptor);
-		mtx_lock(&Giant);
 		error = i386_get_ldt(td, &ldt);
 		td->td_retval[0] *= sizeof(union descriptor);
-		mtx_unlock(&Giant);
 		break;
 	case 0x01: /* write_ldt */
 	case 0x11: /* write_ldt */
@@ -913,9 +909,7 @@
 		desc.sd.sd_xx = 0;
 		desc.sd.sd_def32 = ld.seg_32bit;
 		desc.sd.sd_gran = ld.limit_in_pages;
-		mtx_lock(&Giant);
 		error = i386_set_ldt(td, &ldt, &desc);
-		mtx_unlock(&Giant);
 		break;
 	default:
 		error = EINVAL;
--- //depot/vendor/freebsd/src/sys/kern/kern_timeout.c	2007/05/11 20:57:48
+++ //depot/user/attilio/attilio_smpng/kern/kern_timeout.c	2007/06/22 09:20:49
@@ -46,6 +46,7 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/sleepqueue.h>
 #include <sys/sysctl.h>
 
 static int avg_depth;
@@ -308,7 +309,11 @@
 					 * There is someone waiting
 					 * for the callout to complete.
 					 */
-					wakeup(&callout_wait);
+					mtx_unlock_spin(&callout_lock);
+					sleepq_lock(&callout_wait);
+					mtx_lock_spin(&callout_lock);
+					sleepq_broadcast(&callout_wait,
+					    SLEEPQ_SLEEP, -1, 0);
 					callout_wait = 0;
 				}
 				steps = 0;
@@ -488,6 +493,7 @@
 	struct	callout *c;
 	int	safe;
 {
+	WITNESS_SAVE_DECL(callout_lock);
 	int use_mtx;
 
 	if (!safe && c->c_mtx != NULL) {
@@ -529,9 +535,41 @@
 			 * finish.
 			 */
 			while (c == curr_callout) {
+
+				/*
+				 * Use direct calls to sleepqueue interface
+				 * instead than cv/msleep in order to avoid
+				 * a LOR between callout_lock and sleepqueue
+				 * chain spinlocks.
+				 */
+				mtx_unlock_spin(&callout_lock);
+				sleepq_lock(&callout_wait);
+
+				/*
+				 * Check again the state of curr_callout
+				 * beacause curthread could have lost the
+				 * race previously won.
+				 */
+				mtx_lock_spin(&callout_lock);
+				if (c != curr_callout) {
+					sleepq_release(&callout_wait);
+					break;
+				}
 				callout_wait = 1;
-				msleep_spin(&callout_wait, &callout_lock,
-				    "codrain", 0);
+				DROP_GIANT();
+				WITNESS_SAVE(&callout_lock.lock_object,
+				    callout_lock);
+				mtx_unlock_spin(&callout_lock);
+				sleepq_add(&callout_wait,
+				    &callout_lock.lock_object, "codrain",
+				    SLEEPQ_SLEEP, 0);
+				sleepq_wait(&callout_wait);
+
+				/* Reacquire locks previously released. */
+				PICKUP_GIANT();
+				mtx_lock_spin(&callout_lock);
+				WITNESS_RESTORE(&callout_lock.lock_object,
+				    callout_lock);
 			}
 		} else if (use_mtx && !curr_cancelled) {
 			/*
