--- //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.
@@ -422,6 +420,7 @@
 		if (p->p_flag & P_SA)
 			thread_statclock(1);
 #endif
 		td->td_uticks++;
+		mtx_lock_spin_flags(&time_lock, MTX_QUIET);
 		if (p->p_nice > NZERO)
 			cp_time[CP_NICE]++;
 		else
@@ -442,6 +441,7 @@
 		 */
 		if ((td->td_pflags & TDP_ITHREAD) ||
 		    td->td_intr_nesting_level >= 2) {
 			td->td_iticks++;
+			mtx_lock_spin_flags(&time_lock, MTX_QUIET);
 			cp_time[CP_INTR]++;
 		} else {
 #ifdef KSE
@@ -450,15 +450,18 @@
 				thread_statclock(0);
 #endif
 			td->td_pticks++;
 			td->td_sticks++;
+			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/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_witness.c	2007/04/19 08:07:15
+++ //depot/user/attilio/attilio_schedlock/kern/subr_witness.c	2007/05/04 11:08:21
@@ -410,6 +410,7 @@
 	{ "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 },
 	/*
 	 * leaf locks
 	 */
--- //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)))					\
