--- //depot/vendor/freebsd/src/sys/compat/ndis/kern_windrv.c	2005/11/02 18:05:29
+++ //depot/user/attilio/attilio_schedlock/compat/ndis/kern_windrv.c	2007/01/30 21:17:05
@@ -883,9 +883,9 @@
 	struct gdt		gtable;
 	uint16_t		ltable;
 
-	mtx_lock_spin(&sched_lock);
+	t = curthread;
 
-	t = curthread;
+	mtx_lock_spin(&dt_lock);
 
 	/* Grab location of existing GDT. */
 
@@ -904,7 +904,7 @@
 
 	x86_setldt(&gtable, ltable);
 
-	mtx_unlock_spin(&sched_lock);
+	mtx_unlock_spin(&dt_lock);
 
 	return;
 }
@@ -918,9 +918,9 @@
 	struct x86desc		*l;
 	struct thread		*t;
 
-	mtx_lock_spin(&sched_lock);
+	t = curthread;
 
-	t = curthread;
+	mtx_lock_spin(&dt_lock);
 
 	/* Grab location of existing GDT. */
 
@@ -952,7 +952,7 @@
 
 	x86_setldt(&gtable, ltable);
 
-	mtx_unlock_spin(&sched_lock);
+	mtx_unlock_spin(&dt_lock);
 
 	/* Whew. */
 
--- //depot/vendor/freebsd/src/sys/fs/smbfs/smbfs_io.c	2006/08/09 17:46:32
+++ //depot/user/attilio/attilio_schedlock/fs/smbfs/smbfs_io.c	2007/01/31 20:05:07
@@ -475,8 +475,8 @@
 
 	kva = (vm_offset_t) bp->b_data;
 	pmap_qenter(kva, pages, npages);
-	cnt.v_vnodein++;
-	cnt.v_vnodepgsin += npages;
+	atomic_add_int(&cnt.v_vnodein, 1);
+	atomic_add_int(&cnt.v_vnodepgsin, npages);
 
 	iov.iov_base = (caddr_t) kva;
 	iov.iov_len = count;
@@ -626,8 +626,8 @@
 
 	kva = (vm_offset_t) bp->b_data;
 	pmap_qenter(kva, pages, npages);
-	cnt.v_vnodeout++;
-	cnt.v_vnodepgsout += count;
+	atomic_add_int(&cnt.v_vnodeout, 1);
+	atomic_add_int(&cnt.v_vnodepgsout, count);
 
 	iov.iov_base = (caddr_t) kva;
 	iov.iov_len = count;
--- //depot/vendor/freebsd/src/sys/i386/i386/machdep.c	2007/03/17 19:47:35
+++ //depot/user/attilio/attilio_schedlock/i386/i386/machdep.c	2007/05/08 15:57:49
@@ -1171,8 +1171,10 @@
 	pcb->pcb_gs = _udatasel;
 	load_gs(_udatasel);
 
+	mtx_lock_spin(&dt_lock);
 	if (td->td_proc->p_md.md_ldt)
 		user_ldt_free(td);
+	mtx_unlock_spin(&dt_lock);
   
 	bzero((char *)regs, sizeof(struct trapframe));
 	regs->tf_eip = entry;
@@ -1278,6 +1280,7 @@
 struct gate_descriptor *idt = &idt0[0];	/* interrupt descriptor table */
 union descriptor ldt[NLDT];		/* local descriptor table */
 struct region_descriptor r_gdt, r_idt;	/* table descriptors */
+struct mtx dt_lock;			/* lock for GDT and LDT */
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
 extern int has_f00f_bug;
@@ -2101,6 +2104,7 @@
 
 	r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
 	r_gdt.rd_base =  (int) gdt;
+	mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN);
 	lgdt(&r_gdt);
 
 	pcpu_init(pc, 0, sizeof(struct pcpu));
--- //depot/vendor/freebsd/src/sys/i386/i386/mp_machdep.c	2007/05/08 22:03:14
+++ //depot/user/attilio/attilio_schedlock/i386/i386/mp_machdep.c	2007/05/10 10:36:01
@@ -1388,11 +1388,9 @@
 
 	if (mp_ncpus == 1) 
 		return;
-	mtx_lock_spin(&sched_lock);
 	atomic_store_rel_int(&aps_ready, 1);
 	while (smp_started == 0)
 		ia32_pause();
-	mtx_unlock_spin(&sched_lock);
 }
 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
 
--- //depot/vendor/freebsd/src/sys/i386/i386/sys_machdep.c	2007/04/22 15:36:42
+++ //depot/user/attilio/attilio_schedlock/i386/i386/sys_machdep.c	2007/05/08 16:03:17
@@ -42,6 +42,7 @@
 #include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/smp.h>
 #include <sys/sysproto.h>
 
@@ -115,7 +116,6 @@
 		break;
 	}
 
-	mtx_lock(&Giant);
 	switch(uap->op) {
 	case I386_GET_LDT:
 		error = i386_get_ldt(td, &kargs.largs);
@@ -215,7 +215,6 @@
 		error = EINVAL;
 		break;
 	}
-	mtx_unlock(&Giant);
 	return (error);
 }
 
@@ -351,16 +350,19 @@
 
 /*
  * Update the GDT entry pointing to the LDT to point to the LDT of the
- * current process.
- *
- * This must be called with sched_lock held.  Unfortunately, we can't use a
- * mtx_assert() here because cpu_switch() calls this function after changing
- * curproc but before sched_lock's owner is updated in mi_switch().
+ * current process. Manage dt_lock holding/unholding autonomously.
  */   
 void
 set_user_ldt(struct mdproc *mdp)
 {
 	struct proc_ldt *pldt;
+	int dtlocked;
+
+	dtlocked = 0;
+	if (!mtx_owned(&dt_lock)) {
+		mtx_lock_spin(&dt_lock);
+		dtlocked = 1;
+	}
 
 	pldt = mdp->md_ldt;
 #ifdef SMP
@@ -370,6 +372,8 @@
 #endif
 	lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
 	PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
+	if (dtlocked)
+		mtx_unlock_spin(&dt_lock);
 }
 
 #ifdef SMP
@@ -385,17 +389,15 @@
 #endif
 
 /*
- * Must be called with either sched_lock free or held but not recursed.
- * If it does not return NULL, it will return with it owned.
+ * dt_lock must be held. Returns with dt_lock held.
  */
 struct proc_ldt *
 user_ldt_alloc(struct mdproc *mdp, int len)
 {
 	struct proc_ldt *pldt, *new_ldt;
 
-	if (mtx_owned(&sched_lock))
-		mtx_unlock_spin(&sched_lock);
-	mtx_assert(&sched_lock, MA_NOTOWNED);
+	mtx_assert(&dt_lock, MA_OWNED);
+	mtx_unlock_spin(&dt_lock);
 	MALLOC(new_ldt, struct proc_ldt *, sizeof(struct proc_ldt),
 		M_SUBPROC, M_WAITOK);
 
@@ -406,54 +408,49 @@
 		FREE(new_ldt, M_SUBPROC);
 		return NULL;
 	}
-	new_ldt->ldt_refcnt = 1;
+	refcount_init(&new_ldt->ldt_refcnt, 1);
 	new_ldt->ldt_active = 0;
 
-	mtx_lock_spin(&sched_lock);
+	mtx_lock_spin(&dt_lock);
 	gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base;
 	gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1;
 	ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd);
 
-	if ((pldt = mdp->md_ldt)) {
+	if ((pldt = mdp->md_ldt) != NULL) {
 		if (len > pldt->ldt_len)
 			len = pldt->ldt_len;
 		bcopy(pldt->ldt_base, new_ldt->ldt_base,
 		    len * sizeof(union descriptor));
-	} else {
+	} else
 		bcopy(ldt, new_ldt->ldt_base, sizeof(ldt));
-	}
-	return new_ldt;
+	
+	return (new_ldt);
 }
 
 /*
- * Must be called either with sched_lock free or held but not recursed.
- * If md_ldt is not NULL, it will return with sched_lock released.
+ * Must be called with dt_lock held.
  */
 void
 user_ldt_free(struct thread *td)
 {
 	struct mdproc *mdp = &td->td_proc->p_md;
-	struct proc_ldt *pldt = mdp->md_ldt;
+	struct proc_ldt *pldt;
 
-	if (pldt == NULL)
+	mtx_assert(&dt_lock, MA_OWNED);
+	if ((pldt = mdp->md_ldt) == NULL)
 		return;
 
-	if (!mtx_owned(&sched_lock))
-		mtx_lock_spin(&sched_lock);
-	mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
 	if (td == PCPU_GET(curthread)) {
 		lldt(_default_ldt);
 		PCPU_SET(currentldt, _default_ldt);
 	}
 
 	mdp->md_ldt = NULL;
-	if (--pldt->ldt_refcnt == 0) {
-		mtx_unlock_spin(&sched_lock);
+	if (refcount_release(&pldt->ldt_refcnt)) {
 		kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
 			pldt->ldt_len * sizeof(union descriptor));
 		FREE(pldt, M_SUBPROC);
-	} else
-		mtx_unlock_spin(&sched_lock);
+	}
 }
 
 /*
@@ -468,7 +465,7 @@
 	struct i386_ldt_args *uap;
 {
 	int error = 0;
-	struct proc_ldt *pldt = td->td_proc->p_md.md_ldt;
+	struct proc_ldt *pldt;
 	int nldt, num;
 	union descriptor *lp;
 
@@ -477,11 +474,14 @@
 	    uap->start, uap->num, (void *)uap->descs);
 #endif
 
-	if (pldt) {
+	mtx_lock_spin(&dt_lock);
+	if ((pldt = td->td_proc->p_md.md_ldt) != NULL) {
 		nldt = pldt->ldt_len;
+		lp = &((union descriptor *)(pldt->ldt_base))[uap->start];
+		mtx_unlock_spin(&dt_lock);
 		num = min(uap->num, nldt);
-		lp = &((union descriptor *)(pldt->ldt_base))[uap->start];
 	} else {
+		mtx_unlock_spin(&dt_lock);
 		nldt = sizeof(ldt)/sizeof(ldt[0]);
 		num = min(uap->num, nldt);
 		lp = &ldt[uap->start];
@@ -531,10 +531,10 @@
 		}
 		if (uap->num <= 0)
 			return (EINVAL);
-		mtx_lock_spin(&sched_lock);
-		pldt = mdp->md_ldt;
-		if (pldt == NULL || uap->start >= pldt->ldt_len) {
-			mtx_unlock_spin(&sched_lock);
+		mtx_lock_spin(&dt_lock);
+		if ((pldt = mdp->md_ldt) == NULL ||
+		    uap->start >= pldt->ldt_len) {
+			mtx_unlock_spin(&dt_lock);
 			return (0);
 		}
 		largest_ld = uap->start + uap->num;
@@ -543,7 +543,7 @@
 		i = largest_ld - uap->start;
 		bzero(&((union descriptor *)(pldt->ldt_base))[uap->start],
 		    sizeof(union descriptor) * i);
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&dt_lock);
 		return (0);
 	}
 
@@ -626,15 +626,15 @@
 
 	if (uap->start == LDT_AUTO_ALLOC && uap->num == 1) {
 		/* Allocate a free slot */
-		pldt = mdp->md_ldt;
-		if (pldt == NULL) {
-			error = i386_ldt_grow(td, NLDT + 1);
-			if (error)
+		mtx_lock_spin(&dt_lock);
+		if ((pldt = mdp->md_ldt) == NULL) {
+			if ((error = i386_ldt_grow(td, NLDT + 1))) {
+				mtx_unlock_spin(&dt_lock);
 				return (error);
+			}
 			pldt = mdp->md_ldt;
 		}
 again:
-		mtx_lock_spin(&sched_lock);
 		/*
 		 * start scanning a bit up to leave room for NVidia and
 		 * Wine, which still user the "Blat" method of allocation.
@@ -646,24 +646,23 @@
 			dp++;
 		}
 		if (i >= pldt->ldt_len) {
-			mtx_unlock_spin(&sched_lock);
-			error = i386_ldt_grow(td, pldt->ldt_len+1);
-			if (error)
+			if ((error = i386_ldt_grow(td, pldt->ldt_len+1))) {
+				mtx_unlock_spin(&dt_lock);
 				return (error);
+			}
 			goto again;
 		}
 		uap->start = i;
 		error = i386_set_ldt_data(td, i, 1, descs);
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&dt_lock);
 	} else {
 		largest_ld = uap->start + uap->num;
-		error = i386_ldt_grow(td, largest_ld);
-		if (error == 0) {
-			mtx_lock_spin(&sched_lock);
+		mtx_lock_spin(&dt_lock);
+		if (!(error = i386_ldt_grow(td, largest_ld))) {
 			error = i386_set_ldt_data(td, uap->start, uap->num,
 			    descs);
-			mtx_unlock_spin(&sched_lock);
 		}
+		mtx_unlock_spin(&dt_lock);
 	}
 	if (error == 0)
 		td->td_retval[0] = uap->start;
@@ -677,7 +676,7 @@
 	struct mdproc *mdp = &td->td_proc->p_md;
 	struct proc_ldt *pldt = mdp->md_ldt;
 
-	mtx_assert(&sched_lock, MA_OWNED);
+	mtx_assert(&dt_lock, MA_OWNED);
 
 	/* Fill in range */
 	bcopy(descs,
@@ -694,14 +693,15 @@
 	caddr_t old_ldt_base;
 	int old_ldt_len;
 
+	mtx_assert(&dt_lock, MA_OWNED);
+
 	if (len > MAX_LD)
 		return (ENOMEM);
 	if (len < NLDT + 1)
 		len = NLDT + 1;
 
 	/* Allocate a user ldt. */
-	pldt = mdp->md_ldt;
-	if (!pldt || len > pldt->ldt_len) {
+	if ((pldt = mdp->md_ldt) != NULL || len > pldt->ldt_len) {
 		struct proc_ldt *new_ldt;
 
 		new_ldt = user_ldt_alloc(mdp, len);
@@ -709,42 +709,35 @@
 			return (ENOMEM);
 		pldt = mdp->md_ldt;
 
-		/* sched_lock was acquired by user_ldt_alloc. */
-		if (pldt) {
+		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(&sched_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(&sched_lock);
 			} else {
 				/*
 				 * If other threads already did the work,
 				 * do nothing.
 				 */
-				mtx_unlock_spin(&sched_lock);
 				kmem_free(kernel_map,
 				   (vm_offset_t)new_ldt->ldt_base,
 				   new_ldt->ldt_len * sizeof(union descriptor));
 				FREE(new_ldt, M_SUBPROC);
 				return (0);
 			}
-		} else {
+		} else
 			mdp->md_ldt = pldt = new_ldt;
-		}
 #ifdef SMP
-		mtx_unlock_spin(&sched_lock);
 		/* signal other cpus to reload ldt */
 		smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
 		    NULL, td);
 #else
 		set_user_ldt(mdp);
-		mtx_unlock_spin(&sched_lock);
 #endif
 	}
 	return (0);
--- //depot/vendor/freebsd/src/sys/i386/i386/vm_machdep.c	2007/04/24 21:23:32
+++ //depot/user/attilio/attilio_schedlock/i386/i386/vm_machdep.c	2007/05/08 15:57:49
@@ -62,6 +62,7 @@
 #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>
@@ -158,8 +159,9 @@
 			struct mdproc *mdp1 = &p1->p_md;
 			struct proc_ldt *pldt;
 
+			mtx_lock_spin(&dt_lock);
 			pldt = mdp1->md_ldt;
-			if (pldt && pldt->ldt_refcnt > 1) {
+			if (pldt && refcount_value(&pldt->ldt_refcnt) > 1) {
 				pldt = user_ldt_alloc(mdp1, pldt->ldt_len);
 				if (pldt == NULL)
 					panic("could not copy LDT");
@@ -167,6 +169,7 @@
 				set_user_ldt(mdp1);
 				user_ldt_free(td1);
 			}
+			mtx_unlock_spin(&dt_lock);
 		}
 		return;
 	}
@@ -248,10 +251,10 @@
 	pcb2->pcb_ext = 0;
 
 	/* Copy the LDT, if necessary. */
-	mtx_lock_spin(&sched_lock);
+	mtx_lock_spin(&dt_lock);
 	if (mdp2->md_ldt != NULL) {
 		if (flags & RFMEM) {
-			mdp2->md_ldt->ldt_refcnt++;
+			refcount_acquire(&mdp2->md_ldt->ldt_refcnt);
 		} else {
 			mdp2->md_ldt = user_ldt_alloc(mdp2,
 			    mdp2->md_ldt->ldt_len);
@@ -259,7 +262,7 @@
 				panic("could not copy LDT");
 		}
 	}
-	mtx_unlock_spin(&sched_lock);
+	mtx_unlock_spin(&dt_lock);
 
 	/* Setup to release sched_lock in fork_exit(). */
 	td2->td_md.md_spinlock_count = 1;
@@ -304,11 +307,13 @@
 	 * If this process has a custom LDT, release it.  Reset pc->pcb_gs
 	 * and %gs before we free it in case they refer to an LDT entry.
 	 */
+	mtx_lock_spin(&dt_lock);
 	if (td->td_proc->p_md.md_ldt) {
 		td->td_pcb->pcb_gs = _udatasel;
 		load_gs(_udatasel);
 		user_ldt_free(td);
 	}
+	mtx_unlock_spin(&dt_lock);
 }
 
 void
@@ -696,7 +701,7 @@
 }
 
 /*
- * Get an sf_buf from the freelist.  May block if none are available.
+ * Get an sf_buf from the freelist. Will block if none are available.
  */
 struct sf_buf *
 sf_buf_alloc(struct vm_page *m, int flags)
--- //depot/vendor/freebsd/src/sys/i386/include/proc.h	2005/04/04 21:55:27
+++ //depot/user/attilio/attilio_schedlock/i386/include/proc.h	2007/02/06 00:25:30
@@ -45,6 +45,8 @@
 
 /*
  * Machine-dependent part of the proc structure for i386.
+ * Table of MD locks:
+ *       t - Descriptor tables lock
  */
 struct mdthread {
 	int	md_spinlock_count;	/* (k) */
@@ -52,7 +54,7 @@
 };
 
 struct mdproc {
-	struct proc_ldt *md_ldt;	/* (j) per-process ldt */
+	struct proc_ldt *md_ldt;	/* (t) per-process ldt */
 };
 
 #ifdef	_KERNEL
@@ -61,6 +63,8 @@
 struct 	proc_ldt *user_ldt_alloc(struct mdproc *, int);
 void 	user_ldt_free(struct thread *);
 
+extern struct mtx dt_lock;
+
 #endif	/* _KERNEL */
 
 #endif /* !_MACHINE_PROC_H_ */
--- //depot/vendor/freebsd/src/sys/kern/init_main.c	2007/03/27 16:53:01
+++ //depot/user/attilio/attilio_schedlock/kern/init_main.c	2007/04/14 23:03:36
@@ -496,6 +496,7 @@
 {
 	struct timespec ts;
 	struct proc *p;
+	struct thread *td;
 
 	/*
 	 * Now we can look at the time, having had a chance to verify the
@@ -505,6 +506,10 @@
 	FOREACH_PROC_IN_SYSTEM(p) {
 		microuptime(&p->p_stats->p_start);
 		p->p_rux.rux_runtime = 0;
+		mtx_lock_spin(&sched_lock);
+		FOREACH_THREAD_IN_PROC(p, td)
+			td->td_runtime = 0;
+		mtx_unlock_spin(&sched_lock);
 	}
 	sx_sunlock(&allproc_lock);
 	PCPU_SET(switchtime, cpu_ticks());
--- //depot/vendor/freebsd/src/sys/kern/kern_clock.c	2007/03/08 06:46:41
+++ //depot/user/attilio/attilio_schedlock/kern/kern_clock.c	2007/04/14 23:03:36
@@ -83,6 +83,9 @@
 /* Some of these don't belong here, but it's easiest to concentrate them. */
 long cp_time[CPUSTATES];
 
+/* Spin-lock protecting profiling statistics. */
+struct mtx time_lock;
+
 static int
 sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
 {
@@ -172,6 +175,7 @@
 	 * code do its bit.
 	 */
 	cpu_initclocks();
+	mtx_init(&time_lock, "time lock", NULL, MTX_SPIN);
 
 	/*
 	 * Compute profhz/stathz, and fix profhz if needed.
@@ -349,20 +353,15 @@
 	register struct proc *p;
 {
 
-	/*
-	 * XXX; Right now sched_lock protects statclock(), but perhaps
-	 * it should be protected later on by a time_lock, which would
-	 * cover psdiv, etc. as well.
-	 */
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	if (p->p_flag & P_STOPPROF)
 		return;
 	if ((p->p_flag & P_PROFIL) == 0) {
-		mtx_lock_spin(&sched_lock);
 		p->p_flag |= P_PROFIL;
+		mtx_lock_spin(&time_lock);
 		if (++profprocs == 1)
 			cpu_startprofclock();
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&time_lock);
 	}
 }
 
@@ -385,11 +384,11 @@
 		}
 		if ((p->p_flag & P_PROFIL) == 0)
 			return;
-		mtx_lock_spin(&sched_lock);
 		p->p_flag &= ~P_PROFIL;
+		mtx_lock_spin(&time_lock);
 		if (--profprocs == 0)
 			cpu_stopprofclock();
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&time_lock);
 	}
 }
 
@@ -412,7 +411,6 @@
 	td = curthread;
 	p = td->td_proc;
 
-	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
 	if (usermode) {
 		/*
 		 * Charge the time as appropriate.
@@ -421,7 +419,10 @@
 		if (p->p_flag & P_SA)
 			thread_statclock(1);
 #endif
+		mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
 		td->td_uticks++;
+		mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
+		mtx_lock_spin_flags(&time_lock, MTX_QUIET);
 		if (p->p_nice > NZERO)
 			cp_time[CP_NICE]++;
 		else
@@ -441,7 +442,10 @@
 		 */
 		if ((td->td_pflags & TDP_ITHREAD) ||
 		    td->td_intr_nesting_level >= 2) {
+			mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
 			td->td_iticks++;
+			mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
+			mtx_lock_spin_flags(&time_lock, MTX_QUIET);
 			cp_time[CP_INTR]++;
 		} else {
 #ifdef KSE
@@ -449,16 +453,21 @@
 				thread_statclock(0);
 #endif
 			td->td_pticks++;
+			mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
 			td->td_sticks++;
+			mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
+			mtx_lock_spin_flags(&time_lock, MTX_QUIET);
 			if (!TD_IS_IDLETHREAD(td))
 				cp_time[CP_SYS]++;
 			else
 				cp_time[CP_IDLE]++;
 		}
 	}
+	mtx_unlock_spin_flags(&time_lock, MTX_QUIET);
 	CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
 	    td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz);
 
+	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
 	sched_clock(td);
 
 	/* Update resource usage integrals and maximums. */
--- //depot/vendor/freebsd/src/sys/kern/kern_proc.c	2007/03/23 04:03:03
+++ //depot/user/attilio/attilio_schedlock/kern/kern_proc.c	2007/04/14 23:22:40
@@ -620,7 +620,8 @@
 static void
 fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
 {
-	struct thread *td0;
+	uint64_t calc_rtime;
+	struct thread *td0, *td1;
 	struct tty *tp;
 	struct session *sp;
 	struct ucred *cred;
@@ -693,7 +694,10 @@
 	kp->ki_swtime = p->p_swtime;
 	kp->ki_pid = p->p_pid;
 	kp->ki_nice = p->p_nice;
-	kp->ki_runtime = cputick2usec(p->p_rux.rux_runtime);
+	calc_rtime = 0;
+	FOREACH_THREAD_IN_PROC(p, td1)
+		calc_rtime += td1->td_runtime;
+	kp->ki_runtime = cputick2usec(calc_rtime);
 	mtx_unlock_spin(&sched_lock);
 	if ((p->p_sflag & PS_INMEM) && p->p_stats != NULL) {
 		kp->ki_start = p->p_stats->p_start;
--- //depot/vendor/freebsd/src/sys/kern/kern_resource.c	2007/03/05 13:12:17
+++ //depot/user/attilio/attilio_schedlock/kern/kern_resource.c	2007/04/15 12:23:45
@@ -800,23 +800,21 @@
 	mtx_assert(&sched_lock, MA_NOTOWNED);
 	mtx_lock_spin(&sched_lock);
 
-	/*
-	 * If we are getting stats for the current process, then add in the
-	 * stats that this thread has accumulated in its current time slice.
-	 * We reset the thread and CPU state as if we had performed a context
-	 * switch right here.
-	 */
 	if (curthread->td_proc == p) {
-		td = curthread;
 		u = cpu_ticks();
 		p->p_rux.rux_runtime += u - PCPU_GET(switchtime);
 		PCPU_SET(switchtime, u);
+	}
+
+	FOREACH_THREAD_IN_PROC(p, td) {
+		p->p_rux.rux_runtime += td->td_runtime;
+		p->p_rux.rux_sticks += td->td_sticks;
 		p->p_rux.rux_uticks += td->td_uticks;
+		p->p_rux.rux_iticks += td->td_iticks;
+		td->td_runtime = 0;
+		td->td_sticks = 0;
 		td->td_uticks = 0;
-		p->p_rux.rux_iticks += td->td_iticks;
 		td->td_iticks = 0;
-		p->p_rux.rux_sticks += td->td_sticks;
-		td->td_sticks = 0;
 	}
 	/* Work on a copy of p_rux so we can let go of sched_lock */
 	rux = p->p_rux;
--- //depot/vendor/freebsd/src/sys/kern/kern_synch.c	2007/05/08 21:52:37
+++ //depot/user/attilio/attilio_schedlock/kern/kern_synch.c	2007/05/10 10:36:01
@@ -370,8 +370,8 @@
 void
 mi_switch(int flags, struct thread *newtd)
 {
-	uint64_t new_switchtime;
-	struct thread *td;
+	uint64_t new_switchtime, calc_rtime;
+	struct thread *td, *td1;
 	struct proc *p;
 
 	mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
@@ -410,13 +410,7 @@
 	 * process was running, and add that to its total so far.
 	 */
 	new_switchtime = cpu_ticks();
-	p->p_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
-	p->p_rux.rux_uticks += td->td_uticks;
-	td->td_uticks = 0;
-	p->p_rux.rux_iticks += td->td_iticks;
-	td->td_iticks = 0;
-	p->p_rux.rux_sticks += td->td_sticks;
-	td->td_sticks = 0;
+	td->td_runtime += (new_switchtime - PCPU_GET(switchtime));
 
 	td->td_generation++;	/* bump preempt-detect counter */
 
@@ -424,8 +418,11 @@
 	 * Check if the process exceeds its cpu resource allocation.  If
 	 * it reaches the max, arrange to kill the process in ast().
 	 */
+	calc_rtime = 0;
+	FOREACH_THREAD_IN_PROC(p, td1)
+		calc_rtime += td1->td_runtime;
 	if (p->p_cpulimit != RLIM_INFINITY &&
-	    p->p_rux.rux_runtime >= p->p_cpulimit * cpu_tickrate()) {
+	    calc_rtime >= p->p_cpulimit * cpu_tickrate()) {
 		p->p_sflag |= PS_XCPU;
 		td->td_flags |= TDF_ASTPENDING;
 	}
@@ -433,7 +430,7 @@
 	/*
 	 * Finish up stats for outgoing thread.
 	 */
-	cnt.v_swtch++;
+	atomic_add_int(&cnt.v_swtch, 1);
 	PCPU_SET(switchtime, new_switchtime);
 	PCPU_SET(switchticks, ticks);
 	CTR4(KTR_PROC, "mi_switch: old thread %ld (kse %p, pid %ld, %s)",
--- //depot/vendor/freebsd/src/sys/kern/kern_thread.c	2007/03/27 16:53:01
+++ //depot/user/attilio/attilio_schedlock/kern/kern_thread.c	2007/05/05 22:17:44
@@ -401,13 +401,14 @@
 
 	/* Do the same timestamp bookkeeping that mi_switch() would do. */
 	new_switchtime = cpu_ticks();
-	p->p_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
+	p->p_rux.rux_runtime += td->td_runtime + new_switchtime -
+	    PCPU_GET(switchtime);
 	p->p_rux.rux_uticks += td->td_uticks;
 	p->p_rux.rux_sticks += td->td_sticks;
 	p->p_rux.rux_iticks += td->td_iticks;
 	PCPU_SET(switchtime, new_switchtime);
 	PCPU_SET(switchticks, ticks);
-	cnt.v_swtch++;
+	atomic_add_int(&cnt.v_swtch, 1);
 
 	/* Add our usage into the usage of all our children. */
 	if (p->p_numthreads == 1)
--- //depot/vendor/freebsd/src/sys/kern/subr_prof.c	2007/03/04 22:41:05
+++ //depot/user/attilio/attilio_schedlock/kern/subr_prof.c	2007/04/11 19:21:40
@@ -423,12 +423,12 @@
 	}
 	PROC_LOCK(p);
 	upp = &td->td_proc->p_stats->p_prof;
-	mtx_lock_spin(&sched_lock);
+	mtx_lock_spin(&time_lock);
 	upp->pr_off = uap->offset;
 	upp->pr_scale = uap->scale;
 	upp->pr_base = uap->samples;
 	upp->pr_size = uap->size;
-	mtx_unlock_spin(&sched_lock);
+	mtx_unlock_spin(&time_lock);
 	startprofclock(p);
 	PROC_UNLOCK(p);
 
@@ -468,15 +468,15 @@
 	if (ticks == 0)
 		return;
 	prof = &td->td_proc->p_stats->p_prof;
-	mtx_lock_spin(&sched_lock);
+	mtx_lock_spin(&time_lock);
 	if (pc < prof->pr_off ||
 	    (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size) {
-		mtx_unlock_spin(&sched_lock);		
+		mtx_unlock_spin(&time_lock);		
 		return;			/* out of range; ignore */
 	}
 
 	addr = prof->pr_base + i;
-	mtx_unlock_spin(&sched_lock);
+	mtx_unlock_spin(&time_lock);
 	if ((v = fuswintr(addr)) == -1 || suswintr(addr, v + ticks) == -1) {
 		td->td_profil_addr = pc;
 		td->td_profil_ticks = ticks;
--- //depot/vendor/freebsd/src/sys/kern/subr_trap.c	2007/03/04 22:41:05
+++ //depot/user/attilio/attilio_schedlock/kern/subr_trap.c	2007/04/14 23:22:40
@@ -145,7 +145,8 @@
 void
 ast(struct trapframe *framep)
 {
-	struct thread *td;
+	uint64_t calc_rtime;
+	struct thread *td, *td1;
 	struct proc *p;
 	struct rlimit rlim;
 	int sflag;
@@ -191,8 +192,8 @@
 #endif
 	td->td_flags &= ~(TDF_ASTPENDING | TDF_NEEDSIGCHK |
 	    TDF_NEEDRESCHED | TDF_INTERRUPT);
-	cnt.v_trap++;
 	mtx_unlock_spin(&sched_lock);
+	atomic_add_int(&cnt.v_trap, 1);
 
 	/*
 	 * XXXKSE While the fact that we owe a user profiling
@@ -234,8 +235,11 @@
 	if (sflag & PS_XCPU) {
 		PROC_LOCK(p);
 		lim_rlimit(p, RLIMIT_CPU, &rlim);
+		calc_rtime = 0;
 		mtx_lock_spin(&sched_lock);
-		if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) {
+		FOREACH_THREAD_IN_PROC(p, td1)
+			calc_rtime += td1->td_runtime;
+		if (calc_rtime >= rlim.rlim_max * cpu_tickrate()) {
 			mtx_unlock_spin(&sched_lock);
 			killproc(p, "exceeded maximum CPU limit");
 		} else {
--- //depot/vendor/freebsd/src/sys/kern/subr_witness.c	2007/04/19 08:07:15
+++ //depot/user/attilio/attilio_schedlock/kern/subr_witness.c	2007/05/04 11:08:21
@@ -394,6 +394,7 @@
 	{ "sio", &lock_class_mtx_spin },
 #ifdef __i386__
 	{ "cy", &lock_class_mtx_spin },
+	{ "descriptor tables", &lock_class_mtx_spin },
 #endif
 	{ "scc_hwmtx", &lock_class_mtx_spin },
 	{ "uart_hwmtx", &lock_class_mtx_spin },
@@ -410,6 +411,8 @@
 	{ "callout", &lock_class_mtx_spin },
 	{ "entropy harvest mutex", &lock_class_mtx_spin },
 	{ "syscons video lock", &lock_class_mtx_spin },
+	{ "time lock", &lock_class_mtx_spin },
+	{ "resource manager", &lock_class_mtx_spin },
 	/*
 	 * leaf locks
 	 */
--- //depot/vendor/freebsd/src/sys/nfsclient/nfs_bio.c	2007/04/25 20:37:13
+++ //depot/user/attilio/attilio_schedlock/nfsclient/nfs_bio.c	2007/05/04 11:08:21
@@ -159,8 +159,8 @@
 
 	kva = (vm_offset_t) bp->b_data;
 	pmap_qenter(kva, pages, npages);
-	cnt.v_vnodein++;
-	cnt.v_vnodepgsin += npages;
+	atomic_add_int(&cnt.v_vnodein, 1);
+	atomic_add_int(&cnt.v_vnodepgsin, npages);
 
 	iov.iov_base = (caddr_t) kva;
 	iov.iov_len = count;
@@ -323,8 +323,8 @@
 
 	kva = (vm_offset_t) bp->b_data;
 	pmap_qenter(kva, pages, npages);
-	cnt.v_vnodeout++;
-	cnt.v_vnodepgsout += count;
+	atomic_add_int(&cnt.v_vnodeout, 1);
+	atomic_add_int(&cnt.v_vnodepgsout, count);
 
 	iov.iov_base = (caddr_t) kva;
 	iov.iov_len = count;
--- //depot/vendor/freebsd/src/sys/sys/proc.h	2007/04/24 11:04:30
+++ //depot/user/attilio/attilio_schedlock/sys/proc.h	2007/05/04 11:08:21
@@ -253,12 +253,13 @@
 	struct ucred	*td_ucred;	/* (k) Reference to credentials. */
 	struct thread	*td_standin;	/* (k + a) Use this for an upcall. */
 	struct kse_upcall *td_upcall;	/* (k + j) Upcall structure. */
+	uint64_t	td_runtime;	/* (j) Runtime collected. */
+	uint64_t	td_sticks;	/* (j) Statclock hits in system mode. */
+	uint64_t	td_iticks;	/* (j) Statclock hits in intr mode. */
+	uint64_t	td_uticks;	/* (j) Statclock hits in user mode. */
 	u_int		td_estcpu;	/* (j) Sum of the same field in KSEs. */
 	u_int		td_slptime;	/* (j) How long completely blocked. */
 	u_int		td_pticks;	/* (k) Statclock hits for profiling */
-	u_int		td_sticks;	/* (k) Statclock hits in system mode. */
-	u_int		td_iticks;	/* (k) Statclock hits in intr mode. */
-	u_int		td_uticks;	/* (k) Statclock hits in user mode. */
 	u_int		td_uuticks;	/* (k) Statclock hits (usr), for UTS. */
 	u_int		td_usticks;	/* (k) Statclock hits (sys), for UTS. */
 	int		td_intrval;	/* (j) Return value of TDF_INTERRUPT. */
--- //depot/vendor/freebsd/src/sys/sys/refcount.h	2005/09/27 18:05:29
+++ //depot/user/attilio/attilio_schedlock/sys/refcount.h	2007/01/28 20:01:15
@@ -41,6 +41,13 @@
 	*count = value;
 }
 
+static __inline int
+refcount_value(volatile u_int *count)
+{
+
+	return (*count);
+}
+
 static __inline void
 refcount_acquire(volatile u_int *count)
 {
--- //depot/vendor/freebsd/src/sys/sys/resourcevar.h	2005/12/16 22:10:20
+++ //depot/user/attilio/attilio_schedlock/sys/resourcevar.h	2007/04/14 22:17:09
@@ -121,6 +121,7 @@
 	*lim_hold(struct plimit *limp);
 rlim_t	 lim_max(struct proc *p, int which);
 void	 lim_rlimit(struct proc *p, int which, struct rlimit *rlp);
+void	 resinit(void);
 void	 ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
 	    struct rusage_ext *rux2);
 int	 suswintr(void *base, int word);
--- //depot/vendor/freebsd/src/sys/sys/systm.h	2007/04/08 23:58:46
+++ //depot/user/attilio/attilio_schedlock/sys/systm.h	2007/04/11 19:21:40
@@ -71,6 +71,8 @@
 
 extern int maxusers;		/* system tune hint */
 
+extern struct mtx time_lock;	/* time lock for profiling */
+
 #ifdef	INVARIANTS		/* The option is always available */
 #define	KASSERT(exp,msg) do {						\
 	if (__predict_false(!(exp)))					\
--- //depot/vendor/freebsd/src/sys/vm/swap_pager.c	2007/04/23 14:47:16
+++ //depot/user/attilio/attilio_schedlock/vm/swap_pager.c	2007/05/04 11:08:21
@@ -1037,8 +1037,8 @@
 	}
 	bp->b_npages = j - i;
 
-	cnt.v_swapin++;
-	cnt.v_swappgsin += bp->b_npages;
+	atomic_add_int(&cnt.v_swapin, 1);
+	atomic_add_int(&cnt.v_swappgsin, bp->b_npages);
 
 	/*
 	 * We still hold the lock on mreq, and our automatic completion routine
@@ -1072,7 +1072,7 @@
 		vm_page_lock_queues();
 		vm_page_flag_set(mreq, PG_REFERENCED);
 		vm_page_unlock_queues();
-		cnt.v_intrans++;
+		atomic_add_int(&cnt.v_intrans, 1);
 		if (msleep(mreq, VM_OBJECT_MTX(object), PSWP, "swread", hz*20)) {
 			printf(
 "swap_pager: indefinite wait buffer: bufobj: %p, blkno: %jd, size: %ld\n",
@@ -1263,8 +1263,8 @@
 		bp->b_dirtyoff = 0;
 		bp->b_dirtyend = bp->b_bcount;
 
-		cnt.v_swapout++;
-		cnt.v_swappgsout += bp->b_npages;
+		atomic_add_int(&cnt.v_swapout, 1);
+		atomic_add_int(&cnt.v_swappgsout, bp->b_npages);
 
 		/*
 		 * asynchronous
--- //depot/vendor/freebsd/src/sys/vm/vm_meter.c	2006/11/20 08:36:24
+++ //depot/user/attilio/attilio_schedlock/vm/vm_meter.c	2007/05/10 12:46:10
@@ -52,26 +52,32 @@
 #include <vm/vm_object.h>
 #include <sys/sysctl.h>
 
-struct vmmeter cnt;
+/*
+ * Used to mantain compatibility with sysctl_* functions for the global
+ * vmmeter cnt.
+ */
+#define	CNT_SYSCTL(x)	__DEVOLATILE(u_int *, __CONCAT(&cnt.v_, x))
+
+volatile struct vmmeter cnt;
 
 int maxslp = MAXSLP;
 
 SYSCTL_UINT(_vm, VM_V_FREE_MIN, v_free_min,
-	CTLFLAG_RW, &cnt.v_free_min, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(free_min), 0, "");
 SYSCTL_UINT(_vm, VM_V_FREE_TARGET, v_free_target,
-	CTLFLAG_RW, &cnt.v_free_target, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(free_target), 0, "");
 SYSCTL_UINT(_vm, VM_V_FREE_RESERVED, v_free_reserved,
-	CTLFLAG_RW, &cnt.v_free_reserved, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(free_reserved), 0, "");
 SYSCTL_UINT(_vm, VM_V_INACTIVE_TARGET, v_inactive_target,
-	CTLFLAG_RW, &cnt.v_inactive_target, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(inactive_target), 0, "");
 SYSCTL_UINT(_vm, VM_V_CACHE_MIN, v_cache_min,
-	CTLFLAG_RW, &cnt.v_cache_min, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(cache_min), 0, "");
 SYSCTL_UINT(_vm, VM_V_CACHE_MAX, v_cache_max,
-	CTLFLAG_RW, &cnt.v_cache_max, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(cache_max), 0, "");
 SYSCTL_UINT(_vm, VM_V_PAGEOUT_FREE_MIN, v_pageout_free_min,
-	CTLFLAG_RW, &cnt.v_pageout_free_min, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(pageout_free_min), 0, "");
 SYSCTL_UINT(_vm, OID_AUTO, v_free_severe,
-	CTLFLAG_RW, &cnt.v_free_severe, 0, "");
+	CTLFLAG_RW, CNT_SYSCTL(free_severe), 0, "");
 
 static int
 sysctl_vm_loadavg(SYSCTL_HANDLER_ARGS)
@@ -280,101 +286,103 @@
 SYSCTL_NODE(_vm_stats, OID_AUTO, misc, CTLFLAG_RW, 0, "VM meter misc stats");
 
 SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_swtch, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_swtch, 0, vcnt, "IU", "Context switches");
+	CNT_SYSCTL(swtch), 0, vcnt, "IU", "Context switches");
 SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_trap, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_trap, 0, vcnt, "IU", "Traps");
+	CNT_SYSCTL(trap), 0, vcnt, "IU", "Traps");
 SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_syscall, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_syscall, 0, vcnt, "IU", "Syscalls");
+	CNT_SYSCTL(syscall), 0, vcnt, "IU", "Syscalls");
 SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_intr, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_intr, 0, vcnt, "IU", "Hardware interrupts");
+	CNT_SYSCTL(intr), 0, vcnt, "IU", "Hardware interrupts");
 SYSCTL_PROC(_vm_stats_sys, OID_AUTO, v_soft, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_soft, 0, vcnt, "IU", "Software interrupts");
+	CNT_SYSCTL(soft), 0, vcnt, "IU", "Software interrupts");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vm_faults, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vm_faults, 0, vcnt, "IU", "VM faults");
+	CNT_SYSCTL(vm_faults), 0, vcnt, "IU", "VM faults");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_cow_faults, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_cow_faults, 0, vcnt, "IU", "COW faults");
+	CNT_SYSCTL(cow_faults), 0, vcnt, "IU", "COW faults");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_cow_optim, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_cow_optim, 0, vcnt, "IU", "Optimized COW faults");
+	CNT_SYSCTL(cow_optim), 0, vcnt, "IU", "Optimized COW faults");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_zfod, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_zfod, 0, vcnt, "IU", "Zero fill");
+	CNT_SYSCTL(zfod), 0, vcnt, "IU", "Zero fill");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_ozfod, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_ozfod, 0, vcnt, "IU", "Optimized zero fill");
+	CNT_SYSCTL(ozfod), 0, vcnt, "IU", "Optimized zero fill");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_swapin, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_swapin, 0, vcnt, "IU", "Swapin operations");
+	CNT_SYSCTL(swapin), 0, vcnt, "IU", "Swapin operations");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_swapout, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_swapout, 0, vcnt, "IU", "Swapout operations");
+	CNT_SYSCTL(swapout), 0, vcnt, "IU", "Swapout operations");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_swappgsin, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_swappgsin, 0, vcnt, "IU", "Swapin pages");
+	CNT_SYSCTL(swappgsin), 0, vcnt, "IU", "Swapin pages");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_swappgsout, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_swappgsout, 0, vcnt, "IU", "Swapout pages");
+	CNT_SYSCTL(swappgsout), 0, vcnt, "IU", "Swapout pages");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vnodein, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vnodein, 0, vcnt, "IU", "Vnodein operations");
+	CNT_SYSCTL(vnodein), 0, vcnt, "IU", "Vnodein operations");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vnodeout, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vnodeout, 0, vcnt, "IU", "Vnodeout operations");
+	CNT_SYSCTL(vnodeout), 0, vcnt, "IU", "Vnodeout operations");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vnodepgsin, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vnodepgsin, 0, vcnt, "IU", "Vnodein pages");
+	CNT_SYSCTL(vnodepgsin), 0, vcnt, "IU", "Vnodein pages");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vnodepgsout, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vnodepgsout, 0, vcnt, "IU", "Vnodeout pages");
+	CNT_SYSCTL(vnodepgsout), 0, vcnt, "IU", "Vnodeout pages");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_intrans, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_intrans, 0, vcnt, "IU", "In transit page blocking");
+	CNT_SYSCTL(intrans), 0, vcnt, "IU", "In transit page blocking");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_reactivated, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_reactivated, 0, vcnt, "IU", "Reactivated pages");
+	CNT_SYSCTL(reactivated), 0, vcnt, "IU", "Reactivated pages");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pdwakeups, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_pdwakeups, 0, vcnt, "IU", "Pagedaemon wakeups");
+	CNT_SYSCTL(pdwakeups), 0, vcnt, "IU", "Pagedaemon wakeups");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pdpages, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_pdpages, 0, vcnt, "IU", "Pagedaemon page scans");
+	CNT_SYSCTL(pdpages), 0, vcnt, "IU", "Pagedaemon page scans");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_dfree, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_dfree, 0, vcnt, "IU", "");
+	CNT_SYSCTL(dfree), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pfree, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_pfree, 0, vcnt, "IU", "");
+	CNT_SYSCTL(pfree), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_tfree, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_tfree, 0, vcnt, "IU", "");
+	CNT_SYSCTL(tfree), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_page_size, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_page_size, 0, vcnt, "IU", "");
+	CNT_SYSCTL(page_size), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_page_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_page_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(page_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_free_reserved, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_free_reserved, 0, vcnt, "IU", "");
+	CNT_SYSCTL(free_reserved), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_free_target, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_free_target, 0, vcnt, "IU", "");
+	CNT_SYSCTL(free_target), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_free_min, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_free_min, 0, vcnt, "IU", "");
+	CNT_SYSCTL(free_min), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_free_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_free_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(free_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_wire_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_wire_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(wire_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_active_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_active_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(active_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_inactive_target, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_inactive_target, 0, vcnt, "IU", "");
+	CNT_SYSCTL(inactive_target), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_inactive_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_inactive_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(inactive_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_cache_count, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_cache_count, 0, vcnt, "IU", "");
+	CNT_SYSCTL(cache_count), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_cache_min, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_cache_min, 0, vcnt, "IU", "");
+	CNT_SYSCTL(cache_min), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_cache_max, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_cache_max, 0, vcnt, "IU", "");
+	CNT_SYSCTL(cache_max), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pageout_free_min, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_pageout_free_min, 0, vcnt, "IU", "");
-SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_interrupt_free_min, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_interrupt_free_min, 0, vcnt, "IU", "");
+	CNT_SYSCTL(pageout_free_min), 0, vcnt, "IU", "");
+SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_interrupt_free_min, CTLTYPE_UINT |
+	CTLFLAG_RD, CNT_SYSCTL(interrupt_free_min), 0, vcnt, "IU", "");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_forks, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_forks, 0, vcnt, "IU", "Number of fork() calls");
+	CNT_SYSCTL(forks), 0, vcnt, "IU", "Number of fork() calls");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vforks, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vforks, 0, vcnt, "IU", "Number of vfork() calls");
+	CNT_SYSCTL(vforks), 0, vcnt, "IU", "Number of vfork() calls");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_rforks, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_rforks, 0, vcnt, "IU", "Number of rfork() calls");
+	CNT_SYSCTL(rforks), 0, vcnt, "IU", "Number of rfork() calls");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_kthreads, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_kthreads, 0, vcnt, "IU", "Number of fork() calls by kernel");
+	CNT_SYSCTL(kthreads), 0, vcnt, "IU",
+	"Number of fork() calls by kernel");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_forkpages, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_forkpages, 0, vcnt, "IU", "VM pages affected by fork()");
+	CNT_SYSCTL(forkpages), 0, vcnt, "IU", "VM pages affected by fork()");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_vforkpages, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_vforkpages, 0, vcnt, "IU", "VM pages affected by vfork()");
+	CNT_SYSCTL(vforkpages), 0, vcnt, "IU", "VM pages affected by vfork()");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_rforkpages, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_rforkpages, 0, vcnt, "IU", "VM pages affected by rfork()");
+	CNT_SYSCTL(rforkpages), 0, vcnt, "IU", "VM pages affected by rfork()");
 SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_kthreadpages, CTLTYPE_UINT|CTLFLAG_RD,
-	&cnt.v_kthreadpages, 0, vcnt, "IU", "VM pages affected by fork() by kernel");
+	CNT_SYSCTL(kthreadpages), 0, vcnt, "IU",
+	"VM pages affected by fork() by kernel");
 
 SYSCTL_INT(_vm_stats_misc, OID_AUTO,
 	zero_page_count, CTLFLAG_RD, &vm_page_zero_count, 0, "");
--- //depot/vendor/freebsd/src/sys/vm/vm_object.c	2007/03/27 08:58:09
+++ //depot/user/attilio/attilio_schedlock/vm/vm_object.c	2007/04/11 19:21:40
@@ -655,7 +655,7 @@
 			"p->busy = %d, p->flags %x\n", p, p->busy, p->flags));
 		if (p->wire_count == 0) {
 			vm_page_free(p);
-			cnt.v_pfree++;
+			atomic_add_int(&cnt.v_pfree, 1);
 		} else {
 			vm_page_remove(p);
 		}
--- //depot/vendor/freebsd/src/sys/vm/vm_page.c	2007/05/05 19:54:17
+++ //depot/user/attilio/attilio_schedlock/vm/vm_page.c	2007/05/05 21:22:57
@@ -152,7 +152,7 @@
 vm_set_page_size(void)
 {
 	if (cnt.v_page_size == 0)
-		cnt.v_page_size = PAGE_SIZE;
+		atomic_store_rel_int(&cnt.v_page_size, PAGE_SIZE);
 	if (((cnt.v_page_size - 1) & cnt.v_page_size) != 0)
 		panic("vm_set_page_size: page size not a power of two");
 }
@@ -357,8 +357,8 @@
 	 * last rather than first.  On large-memory machines, this avoids
 	 * the exhaustion of low physical memory before isa_dma_init has run.
 	 */
-	cnt.v_page_count = 0;
-	cnt.v_free_count = 0;
+	atomic_store_rel_int(&cnt.v_page_count, 0);
+	atomic_store_rel_int(&cnt.v_free_count, 0);
 	list = getenv("vm.blacklist");
 	for (i = 0; phys_avail[i + 1] != 0; i += 2) {
 		pa = phys_avail[i];
@@ -1045,7 +1045,7 @@
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
 	if (VM_PAGE_GETKNOWNQUEUE2(m) != PQ_ACTIVE) {
 		if (VM_PAGE_INQUEUE1(m, PQ_CACHE))
-			cnt.v_reactivated++;
+			atomic_add_int(&cnt.v_reactivated, 1);
 		vm_pageq_remove(m);
 		if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) {
 			if (m->act_count < ACT_INIT)
@@ -1112,7 +1112,7 @@
 		mtx_assert(&vm_page_queue_mtx, MA_OWNED);
 	KASSERT(!pmap_page_is_mapped(m),
 	    ("vm_page_free_toq: freeing mapped page %p", m));
-	cnt.v_tfree++;
+	atomic_add_int(&cnt.v_tfree, 1);
 
 	if (m->busy || VM_PAGE_INQUEUE1(m, PQ_FREE)) {
 		printf(
@@ -1286,7 +1286,7 @@
 		return;
 	if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) {
 		if (VM_PAGE_INQUEUE1(m, PQ_CACHE))
-			cnt.v_reactivated++;
+			atomic_add_int(&cnt.v_reactivated, 1);
 		vm_page_flag_clear(m, PG_WINATCFLS);
 		vm_pageq_remove(m);
 		if (athead)
@@ -1295,7 +1295,7 @@
 			TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
 		VM_PAGE_SETQUEUE2(m, PQ_INACTIVE);
 		vm_page_queues[PQ_INACTIVE].lcnt++;
-		cnt.v_inactive_count++;
+		atomic_add_int(&cnt.v_inactive_count, 1);
 	}
 }
 
--- //depot/vendor/freebsd/src/sys/vm/vm_pageout.c	2007/02/07 06:41:32
+++ //depot/user/attilio/attilio_schedlock/vm/vm_pageout.c	2007/02/15 13:38:28
@@ -538,7 +538,7 @@
 				goto unlock_return;
 			}
 			next = TAILQ_NEXT(p, listq);
-			cnt.v_pdpages++;
+			atomic_add_int(&cnt.v_pdpages, 1);
 			if (p->wire_count != 0 ||
 			    p->hold_count != 0 ||
 			    p->busy != 0 ||
@@ -856,7 +856,7 @@
 			 * Invalid pages can be easily freed
 			 */
 			vm_page_free(m);
-			cnt.v_dfree++;
+			atomic_add_int(&cnt.v_dfree, 1);
 			--page_shortage;
 		} else if (m->dirty == 0) {
 			/*
@@ -1409,7 +1409,7 @@
 	/*
 	 * Initialize some paging parameters.
 	 */
-	cnt.v_interrupt_free_min = 2;
+	atomic_store_rel_int(&cnt.v_interrupt_free_min, 2);
 	if (cnt.v_page_count < 2000)
 		vm_pageout_page_count = 8;
 
@@ -1418,17 +1418,15 @@
 	 * swap pager structures plus enough for any pv_entry structs
 	 * when paging. 
 	 */
-	if (cnt.v_page_count > 1024)
-		cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200;
-	else
-		cnt.v_free_min = 4;
-	cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE +
-	    cnt.v_interrupt_free_min;
-	cnt.v_free_reserved = vm_pageout_page_count +
-	    cnt.v_pageout_free_min + (cnt.v_page_count / 768) + PQ_NUMCOLORS;
-	cnt.v_free_severe = cnt.v_free_min / 2;
-	cnt.v_free_min += cnt.v_free_reserved;
-	cnt.v_free_severe += cnt.v_free_reserved;
+	atomic_store_rel_int(&cnt.v_free_min, (cnt.v_page_count > 1024) ?
+	    (4 + (cnt.v_page_count - 1024) / 200) : 4);
+	atomic_store_rel_int(&cnt.v_pageout_free_min, (2 * MAXBSIZE) /
+	    PAGE_SIZE + cnt.v_interrupt_free_min);
+	atomic_store_rel_int(&cnt.v_free_reserved, vm_pageout_page_count +
+	    cnt.v_pageout_free_min + (cnt.v_page_count / 768) + PQ_NUMCOLORS);
+	atomic_store_rel_int(&cnt.v_free_severe, cnt.v_free_min / 2);
+	atomic_add_int(&cnt.v_free_min, cnt.v_free_reserved);
+	atomic_add_int(&cnt.v_free_severe, cnt.v_free_reserved);
 
 	/*
 	 * v_free_target and v_cache_min control pageout hysteresis.  Note
@@ -1441,22 +1439,23 @@
 	 * be big enough to handle memory needs while the pageout daemon
 	 * is signalled and run to free more pages.
 	 */
-	if (cnt.v_free_count > 6144)
-		cnt.v_free_target = 4 * cnt.v_free_min + cnt.v_free_reserved;
-	else
-		cnt.v_free_target = 2 * cnt.v_free_min + cnt.v_free_reserved;
+	atomic_store_rel_int(&cnt.v_free_target, ((cnt.v_free_count > 6144) ?
+	    4 : 2) * cnt.v_free_min + cnt.v_free_reserved);
 
 	if (cnt.v_free_count > 2048) {
-		cnt.v_cache_min = cnt.v_free_target;
-		cnt.v_cache_max = 2 * cnt.v_cache_min;
-		cnt.v_inactive_target = (3 * cnt.v_free_target) / 2;
+		atomic_store_rel_int(&cnt.v_cache_min, cnt.v_free_target);
+		atomic_store_rel_int(&cnt.v_cache_max, 2 * cnt.v_cache_min);
+		atomic_store_rel_int(&cnt.v_inactive_target, (3 *
+		    cnt.v_free_target) / 2);
 	} else {
-		cnt.v_cache_min = 0;
-		cnt.v_cache_max = 0;
-		cnt.v_inactive_target = cnt.v_free_count / 4;
+		atomic_store_rel_int(&cnt.v_cache_min, 0);
+		atomic_store_rel_int(&cnt.v_cache_max, 0);
+		atomic_store_rel_int(&cnt.v_inactive_target,
+		    cnt.v_free_count / 4);
 	}
 	if (cnt.v_inactive_target > cnt.v_free_count / 3)
-		cnt.v_inactive_target = cnt.v_free_count / 3;
+		atomic_store_rel_int(&cnt.v_inactive_target,
+		    cnt.v_free_count / 3);
 
 	/* XXX does not really belong here */
 	if (vm_page_max_wired == 0)
@@ -1524,7 +1523,7 @@
 			}
 		}
 		if (vm_pages_needed)
-			cnt.v_pdwakeups++;
+			atomic_add_int(&cnt.v_pdwakeups, 1);
 		mtx_unlock(&vm_page_queue_free_mtx);
 		vm_pageout_scan(pass);
 	}
--- //depot/vendor/freebsd/src/sys/vm/vnode_pager.c	2006/10/14 23:26:11
+++ //depot/user/attilio/attilio_schedlock/vm/vnode_pager.c	2007/01/31 20:05:07
@@ -728,8 +728,8 @@
 			if (i != reqpage)
 				vm_page_free(m[i]);
 		vm_page_unlock_queues();
-		cnt.v_vnodein++;
-		cnt.v_vnodepgsin++;
+		atomic_add_int(&cnt.v_vnodein, 1);
+		atomic_add_int(&cnt.v_vnodepgsin, 1);
 		error = vnode_pager_input_old(object, m[reqpage]);
 		VM_OBJECT_UNLOCK(object);
 		return (error);
@@ -757,8 +757,8 @@
 				vm_page_free(m[i]);
 		vm_page_unlock_queues();
 		VM_OBJECT_UNLOCK(object);
-		cnt.v_vnodein++;
-		cnt.v_vnodepgsin++;
+		atomic_add_int(&cnt.v_vnodein, 1);
+		atomic_add_int(&cnt.v_vnodepgsin, 1);
 		return vnode_pager_input_smlfs(object, m[reqpage]);
 	}
 
@@ -909,8 +909,8 @@
 	bp->b_runningbufspace = bp->b_bufsize;
 	atomic_add_int(&runningbufspace, bp->b_runningbufspace);
 
-	cnt.v_vnodein++;
-	cnt.v_vnodepgsin += count;
+	atomic_add_int(&cnt.v_vnodein, 1);
+	atomic_add_int(&cnt.v_vnodepgsin, count);
 
 	/* do the input */
 	bp->b_iooffset = dbtob(bp->b_blkno);
@@ -1157,8 +1157,8 @@
 	auio.uio_resid = maxsize;
 	auio.uio_td = (struct thread *) 0;
 	error = VOP_WRITE(vp, &auio, ioflags, curthread->td_ucred);
-	cnt.v_vnodeout++;
-	cnt.v_vnodepgsout += ncount;
+	atomic_add_int(&cnt.v_vnodeout, 1);
+	atomic_add_int(&cnt.v_vnodepgsout, ncount);
 
 	if (error) {
 		if ((ppscheck = ppsratecheck(&lastfail, &curfail, 1)))
