--- //depot/vendor/freebsd/src/sys/compat/linux/linux_misc.c	2007/05/31 22:58:09
+++ //depot/user/attilio/attilio_schedlock/compat/linux/linux_misc.c	2007/06/08 23:25:40
@@ -670,7 +670,9 @@
 	if (args->buf != NULL) {
 		p = td->td_proc;
 		PROC_LOCK(p);
+		PROC_SLOCK(p);
 		calcru(p, &utime, &stime);
+		PROC_SUNLOCK(p);
 		calccru(p, &cutime, &cstime);
 		PROC_UNLOCK(p);
 
--- //depot/vendor/freebsd/src/sys/compat/svr4/svr4_misc.c	2007/06/05 00:07:29
+++ //depot/user/attilio/attilio_schedlock/compat/svr4/svr4_misc.c	2007/06/09 15:26:49
@@ -828,7 +828,9 @@
 
 	p = td->td_proc;
 	PROC_LOCK(p);
+	PROC_SLOCK(p);
 	calcru(p, &utime, &stime);
+	PROC_SUNLOCK(p);
 	calccru(p, &cutime, &cstime);
 	PROC_UNLOCK(p);
 
@@ -1239,7 +1241,9 @@
 			pid = p->p_pid;
 			status = p->p_xstat;
 			ru = *p->p_ru;
+			PROC_SLOCK(p);
 			calcru(p, &ru.ru_utime, &ru.ru_stime);
+			PROC_SUNLOCK(p);
 			PROC_UNLOCK(p);
 			sx_sunlock(&proctree_lock);
 
@@ -1265,7 +1269,9 @@
 			pid = p->p_pid;
 			status = W_STOPCODE(p->p_xstat);
 			ru = *p->p_ru;
+			PROC_SLOCK(p);
 			calcru(p, &ru.ru_utime, &ru.ru_stime);
+			PROC_SUNLOCK(p);
 			PROC_UNLOCK(p);
 
 		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
@@ -1287,7 +1293,9 @@
 			pid = p->p_pid;
 			ru = *p->p_ru;
 			status = SIGCONT;
+			PROC_SLOCK(p);
 			calcru(p, &ru.ru_utime, &ru.ru_stime);
+			PROC_SUNLOCK(p);
 			PROC_UNLOCK(p);
 
 		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
--- //depot/vendor/freebsd/src/sys/fs/procfs/procfs_status.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/fs/procfs/procfs_status.c	2007/06/08 22:52:23
@@ -127,12 +127,12 @@
 		} else
 			wmesg = "nochan";
 	}
-	PROC_SUNLOCK(p);
 
 	if (p->p_sflag & PS_INMEM) {
 		struct timeval start, ut, st;
 
 		calcru(p, &ut, &st);
+		PROC_SUNLOCK(p);
 		start = p->p_stats->p_start;
 		timevaladd(&start, &boottime);
 		sbuf_printf(sb, " %jd,%ld %jd,%ld %jd,%ld",
@@ -140,6 +140,7 @@
 		    (intmax_t)ut.tv_sec, ut.tv_usec,
 		    (intmax_t)st.tv_sec, st.tv_usec);
 	} else {
+		PROC_SUNLOCK(p);
 		sbuf_printf(sb, " -1,-1 -1,-1 -1,-1");
 	}
 
--- //depot/vendor/freebsd/src/sys/kern/kern_acct.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/kern/kern_acct.c	2007/06/08 23:16:24
@@ -370,8 +370,7 @@
 	bcopy(p->p_comm, acct.ac_comm, sizeof acct.ac_comm);
 
 	/* (2) The amount of user and system time that was used */
-	rufetch(p, &ru);
-	calcru(p, &ut, &st);
+	rufetchcalc(p, &ru, &ut, &st);
 	acct.ac_utime = encode_timeval(ut);
 	acct.ac_stime = encode_timeval(st);
 
--- //depot/vendor/freebsd/src/sys/kern/kern_exit.c	2007/06/07 22:40:16
+++ //depot/user/attilio/attilio_schedlock/kern/kern_exit.c	2007/06/09 15:39:19
@@ -725,16 +725,14 @@
 			 * XXX This is questionable.
 			 */
 			PROC_SLOCK(p);
+			if (rusage) {
+				*rusage = *p->p_ru;
+				calcru(p, &rusage->ru_utime, &rusage->ru_stime);
+			}
 			PROC_SUNLOCK(p);
-			
 			td->td_retval[0] = p->p_pid;
 			if (status)
 				*status = p->p_xstat;	/* convert to int */
-			if (rusage) {
-				*rusage = *p->p_ru;
-				calcru(p, &rusage->ru_utime, &rusage->ru_stime);
-			}
-
 			PROC_LOCK(q);
 			sigqueue_take(p->p_ksi);
 			PROC_UNLOCK(q);
--- //depot/vendor/freebsd/src/sys/kern/kern_proc.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/kern/kern_proc.c	2007/06/08 22:52:23
@@ -700,7 +700,9 @@
 	if ((p->p_sflag & PS_INMEM) && p->p_stats != NULL) {
 		kp->ki_start = p->p_stats->p_start;
 		timevaladd(&kp->ki_start, &boottime);
+		PROC_SLOCK(p);
 		calcru(p, &kp->ki_rusage.ru_utime, &kp->ki_rusage.ru_stime);
+		PROC_SUNLOCK(p);
 		calccru(p, &kp->ki_childutime, &kp->ki_childstime);
 
 		/* Some callers want child-times in a single value */
--- //depot/vendor/freebsd/src/sys/kern/kern_resource.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/kern/kern_resource.c	2007/06/08 23:16:24
@@ -829,12 +829,11 @@
 void
 calcru(struct proc *p, struct timeval *up, struct timeval *sp)
 {
-	struct rusage_ext rux;
 	struct thread *td;
 	uint64_t u;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
-	PROC_SLOCK(p);
+	PROC_SLOCK_ASSERT(p, MA_OWNED);
 	/*
 	 * If we are getting stats for the current process, then add in the
 	 * stats that this thread has accumulated in its current time slice.
@@ -847,14 +846,7 @@
 		p->p_rux.rux_runtime += u - PCPU_GET(switchtime);
 		PCPU_SET(switchtime, u);
 	}
-	/* Work on a copy of p_rux so we can let go of p_slock */
-	rux = p->p_rux;
-	PROC_SUNLOCK(p);
-	calcru1(p, &rux, up, sp);
-	/* Update the result from the p_rux copy */
-	p->p_rux.rux_uu = rux.rux_uu;
-	p->p_rux.rux_su = rux.rux_su;
-	p->p_rux.rux_tu = rux.rux_tu;
+	calcru1(p, &p->p_rux, up, sp);
 }
 
 static void
@@ -965,8 +957,8 @@
 	switch (who) {
 
 	case RUSAGE_SELF:
-		rufetch(p, rup);
-		calcru(p, &rup->ru_utime, &rup->ru_stime);
+		rufetchcalc(p, rup, &rup->ru_utime,
+		    &rup->ru_stime);
 		break;
 
 	case RUSAGE_CHILDREN:
@@ -1039,8 +1031,9 @@
 {
 	struct thread *td;
 
+	PROC_SLOCK_ASSERT(p, MA_OWNED);
+
 	memset(ru, 0, sizeof(*ru));
-	PROC_SLOCK(p);
 	if (p->p_ru == NULL)  {
 		KASSERT(p->p_numthreads > 0,
 		    ("rufetch: No threads or ru in proc %p", p));
@@ -1052,6 +1045,21 @@
 		}
 	} else
 		*ru = *p->p_ru;
+}
+
+/*
+ * Atomically perform a rufetch and a calcru together.
+ * Consumers, can safely assume the calcru is executed only once
+ * rufetch is completed.
+ */
+void
+rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
+    struct timeval *sp)
+{
+
+	PROC_SLOCK(p);
+	rufetch(p, ru);
+	calcru(p, up, sp);
 	PROC_SUNLOCK(p);
 }
 
--- //depot/vendor/freebsd/src/sys/kern/kern_time.c	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/kern/kern_time.c	2007/06/08 22:52:23
@@ -213,13 +213,17 @@
 		break;
 	case CLOCK_VIRTUAL:
 		PROC_LOCK(p);
+		PROC_SLOCK(p);
 		calcru(p, &user, &sys);
+		PROC_SUNLOCK(p);
 		PROC_UNLOCK(p);
 		TIMEVAL_TO_TIMESPEC(&user, ats);
 		break;
 	case CLOCK_PROF:
 		PROC_LOCK(p);
+		PROC_SLOCK(p);
 		calcru(p, &user, &sys);
+		PROC_SUNLOCK(p);
 		PROC_UNLOCK(p);
 		timevaladd(&user, &sys);
 		TIMEVAL_TO_TIMESPEC(&user, ats);
--- //depot/vendor/freebsd/src/sys/sys/resourcevar.h	2007/06/05 00:03:37
+++ //depot/user/attilio/attilio_schedlock/sys/resourcevar.h	2007/06/08 23:16:24
@@ -123,8 +123,10 @@
 void	 lim_rlimit(struct proc *p, int which, struct rlimit *rlp);
 void	 ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
 	    struct rusage_ext *rux2);
+void	 rucollect(struct rusage *ru, struct rusage *ru2);
 void	 rufetch(struct proc *p, struct rusage *ru);
-void	 rucollect(struct rusage *ru, struct rusage *ru2);
+void	 rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
+	    struct timeval *sp);
 void	 ruxagg(struct rusage_ext *rux, struct thread *td);
 int	 suswintr(void *base, int word);
 struct uidinfo
