--- /usr/src/sys/kern/init_main.c	2007/05/18 07:13:35
+++ kern/init_main.c	2007/05/18 15:48:50
@@ -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());
--- /usr/src/sys/kern/kern_clock.c	2007/05/20 22:18:03
+++ kern/kern_clock.c	2007/05/20 23:48:29
@@ -419,7 +419,9 @@
 		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]++;
@@ -440,7 +442,9 @@
 		 */
 		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 {
@@ -449,7 +453,9 @@
 				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]++;
--- /usr/src/sys/kern/kern_proc.c	2007/03/23 04:03:03
+++ 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;
--- /usr/src/sys/kern/kern_resource.c	2007/05/14 22:42:46
+++ kern/kern_resource.c	2007/05/16 21:04:21
@@ -796,23 +796,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;
--- /usr/src/sys/kern/kern_synch.c	2007/05/18 07:13:35
+++ kern/kern_synch.c	2007/05/18 15:48:50
@@ -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;
 	}
--- /usr/src/sys/kern/kern_thread.c	2007/05/18 07:13:35
+++ kern/kern_thread.c	2007/05/18 15:48:50
@@ -401,7 +401,8 @@
 
 	/* 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;
--- /usr/src/sys/kern/subr_trap.c	2007/05/18 07:13:35
+++ kern/subr_trap.c	2007/05/21 15:16:53
@@ -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;
@@ -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 {
--- /usr/src/sys/kern/subr_witness.c	2007/05/20 22:18:03
+++ kern/subr_witness.c	2007/05/20 23:48:29
@@ -411,6 +411,7 @@
 	{ "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
 	 */
--- /usr/src/sys/sys/proc.h	2007/04/24 11:04:30
+++ 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. */
