--- /usr/src/sys/kern/init_main.c	Mon Apr  2 00:23:28 2007
+++ init_main.c	Wed Apr 11 19:00:29 2007
@@ -495,6 +495,7 @@
 proc0_post(void *dummy __unused)
 {
 	struct timespec ts;
+	struct thread *td;
 	struct proc *p;
 
 	/*
@@ -504,7 +505,8 @@
 	sx_slock(&allproc_lock);
 	FOREACH_PROC_IN_SYSTEM(p) {
 		microuptime(&p->p_stats->p_start);
-		p->p_rux.rux_runtime = 0;
+		FOREACH_THREAD_IN_PROC(p, td)
+			td->td_rux.rux_runtime = 0;
 	}
 	sx_sunlock(&allproc_lock);
 	PCPU_SET(switchtime, cpu_ticks());
--- /usr/src/sys/kern/kern_clock.c	Fri Mar  9 03:33:20 2007
+++ kern_clock.c	Wed Apr 11 19:02:32 2007
@@ -397,7 +397,7 @@
  * Statistics clock.  Grab profile sample, and if divider reaches 0,
  * do process and kernel statistics.  Most of the statistics are only
  * used by user-level statistics programs.  The main exceptions are
- * ke->ke_uticks, p->p_rux.rux_sticks, p->p_rux.rux_iticks, and p->p_estcpu.
+ * ke->ke_uticks, td->td_rux.rux_sticks, td->td_rux.rux_iticks, and p->p_estcpu.
  * This should be called by all active processors.
  */
 void
--- /usr/src/sys/kern/kern_exit.c	Fri Mar 23 01:37:54 2007
+++ kern_exit.c	Thu Apr 12 00:27:50 2007
@@ -660,6 +660,8 @@
 kern_wait(struct thread *td, pid_t pid, int *status, int options,
     struct rusage *rusage)
 {
+	struct rusage_ext ruxobj;
+	struct thread *td1;
 	struct proc *p, *q, *t;
 	int error, nfound;
 
@@ -771,9 +773,19 @@
 			PROC_LOCK(p);
 			p->p_xstat = 0;		/* XXX: why? */
 			PROC_UNLOCK(p);
+			bzero(&ruxobj, sizeof(ruxobj));
+			mtx_lock_spin(&sched_lock);
+			FOREACH_THREAD_IN_PROC(p, td1) {
+				ruxobj.rux_runtime += td1->td_rux.rux_runtime;
+				ruxobj.rux_uticks += td1->td_rux.rux_uticks;
+				ruxobj.rux_sticks += td1->td_rux.rux_sticks;
+				ruxobj.rux_iticks += td1->td_rux.rux_iticks;
+			}
+			mtx_unlock_spin(&sched_lock);
+			td1 = FIRST_THREAD_IN_PROC(q);
 			PROC_LOCK(q);
-			ruadd(&q->p_stats->p_cru, &q->p_crux, p->p_ru,
-			    &p->p_rux);
+			ruadd(&q->p_stats->p_cru, &q->p_crux, &td1->td_crux,
+			    p->p_ru, &p->p_rux, &ruxobj);
 			PROC_UNLOCK(q);
 			FREE(p->p_ru, M_ZOMBIE);
 			p->p_ru = NULL;
--- /usr/src/sys/kern/kern_proc.c	Fri Mar 23 22:51:53 2007
+++ kern_proc.c	Wed Mar  7 00:16:09 2007
@@ -620,13 +620,15 @@
 static void
 fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
 {
-	struct thread *td0;
+	uint64_t calc_runtime;
+	struct thread *td0, *td1;
 	struct tty *tp;
 	struct session *sp;
 	struct ucred *cred;
 	struct sigacts *ps;
 
 	bzero(kp, sizeof(*kp));
+	calc_runtime = 0;
 
 	kp->ki_structsize = sizeof(*kp);
 	kp->ki_paddr = p;
@@ -693,7 +695,9 @@
 	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);
+	FOREACH_THREAD_IN_PROC(p, td1)
+		calc_runtime += td1->td_rux.rux_runtime;
+	kp->ki_runtime = cputick2usec(calc_runtime);
 	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	Thu Mar  8 05:34:06 2007
+++ kern_resource.c	Thu Apr 12 00:28:09 2007
@@ -71,7 +71,8 @@
 static u_long uihash;		/* size of hash table - 1 */
 
 static void	calcru1(struct proc *p, struct rusage_ext *ruxp,
-		    struct timeval *up, struct timeval *sp);
+		    struct rusage_ext_tm *ruxtmp, struct timeval *up,
+		    struct timeval *sp);
 static int	donice(struct thread *td, struct proc *chgp, int n);
 static struct uidinfo *uilookup(uid_t uid);
 
@@ -779,9 +780,18 @@
 	struct timeval *up;
 	struct timeval *sp;
 {
+	struct rusage_ext rux;
+	struct thread *td;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
-	calcru1(p, &p->p_crux, up, sp);
+	bzero(&rux, sizeof(rux));
+	FOREACH_THREAD_IN_PROC(p, td) {
+		rux.rux_runtime += td->td_rux.rux_runtime;
+		rux.rux_uticks += td->td_rux.rux_uticks;
+		rux.rux_sticks += td->td_rux.rux_sticks;
+		rux.rux_iticks += td->td_rux.rux_iticks;
+	}
+	calcru1(p, &rux, &p->p_crux, up, sp);
 }
 
 /*
@@ -806,31 +816,34 @@
 	 * 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);
-		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;
+	FOREACH_THREAD_IN_PROC(p, td) {
+		if (td == curthread) {
+			u = cpu_ticks();
+			td->td_rux.rux_runtime += u - PCPU_GET(switchtime);
+			PCPU_SET(switchtime, u);
+			td->td_rux.rux_uticks += td->td_uticks;
+			td->td_uticks = 0;
+			td->td_rux.rux_iticks += td->td_iticks;
+			td->td_iticks = 0;
+			td->td_rux.rux_sticks += td->td_sticks;
+			td->td_sticks = 0;
+		}
+	}
+	/* Work on a copy of global rux so we can let go of sched_lock */
+	bzero(&rux, sizeof(rux));
+	FOREACH_THREAD_IN_PROC(p, td) {
+		rux.rux_runtime += td->td_rux.rux_runtime;
+		rux.rux_uticks += td->td_rux.rux_uticks;
+		rux.rux_sticks += td->td_rux.rux_sticks;
+		rux.rux_iticks += td->td_rux.rux_iticks;
 	}
-	/* Work on a copy of p_rux so we can let go of sched_lock */
-	rux = p->p_rux;
 	mtx_unlock_spin(&sched_lock);
-	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, &rux, &p->p_rux, up, sp);
 }
 
 static void
-calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
-    struct timeval *sp)
+calcru1(struct proc *p, struct rusage_ext *ruxp, struct rusage_ext_tm *ruxtmp,
+    struct timeval *up, struct timeval *sp)
 {
 	/* {user, system, interrupt, total} {ticks, usec}: */
 	u_int64_t ut, uu, st, su, it, tt, tu;
@@ -849,21 +862,21 @@
 		/* XXX: this should be an assert /phk */
 		printf("calcru: negative runtime of %jd usec for pid %d (%s)\n",
 		    (intmax_t)tu, p->p_pid, p->p_comm);
-		tu = ruxp->rux_tu;
+		tu = ruxtmp->rux_tu;
 	}
 
-	if (tu >= ruxp->rux_tu) {
+	if (tu >= ruxtmp->rux_tu) {
 		/*
 		 * The normal case, time increased.
 		 * Enforce monotonicity of bucketed numbers.
 		 */
 		uu = (tu * ut) / tt;
-		if (uu < ruxp->rux_uu)
-			uu = ruxp->rux_uu;
+		if (uu < ruxtmp->rux_uu)
+			uu = ruxtmp->rux_uu;
 		su = (tu * st) / tt;
-		if (su < ruxp->rux_su)
-			su = ruxp->rux_su;
-	} else if (tu + 3 > ruxp->rux_tu || 101 * tu > 100 * ruxp->rux_tu) {
+		if (su < ruxtmp->rux_su)
+			su = ruxtmp->rux_su;
+	} else if (tu + 3 > ruxtmp->rux_tu || 101 * tu > 100 * ruxtmp->rux_tu) {
 		/* 
 		 * When we calibrate the cputicker, it is not uncommon to
 		 * see the presumably fixed frequency increase slightly over
@@ -873,10 +886,10 @@
  		 * shortly.  We use a 3 microsecond limit to catch low
 		 * counts and a 1% limit for high counts.
 		 */
-		uu = ruxp->rux_uu;
-		su = ruxp->rux_su;
-		tu = ruxp->rux_tu;
-	} else { /* tu < ruxp->rux_tu */
+		uu = ruxtmp->rux_uu;
+		su = ruxtmp->rux_su;
+		tu = ruxtmp->rux_tu;
+	} else { /* tu < ruxtmp->rux_tu */
 		/*
 		 * What happene here was likely that a laptop, which ran at
 		 * a reduced clock frequency at boot, kicked into high gear.
@@ -887,15 +900,15 @@
 		 */
 		printf("calcru: runtime went backwards from %ju usec "
 		    "to %ju usec for pid %d (%s)\n",
-		    (uintmax_t)ruxp->rux_tu, (uintmax_t)tu,
+		    (uintmax_t)ruxtmp->rux_tu, (uintmax_t)tu,
 		    p->p_pid, p->p_comm);
 		uu = (tu * ut) / tt;
 		su = (tu * st) / tt;
 	}
 
-	ruxp->rux_uu = uu;
-	ruxp->rux_su = su;
-	ruxp->rux_tu = tu;
+	ruxtmp->rux_uu = uu;
+	ruxtmp->rux_su = su;
+	ruxtmp->rux_tu = tu;
 
 	up->tv_sec = uu / 1000000;
 	up->tv_usec = uu % 1000000;
@@ -954,10 +967,12 @@
 }
 
 void
-ruadd(ru, rux, ru2, rux2)
+ruadd(ru, ruxtm, rux, ru2, ruxtm2, rux2)
 	struct rusage *ru;
+	struct rusage_ext_tm *ruxtm;
 	struct rusage_ext *rux;
 	struct rusage *ru2;
+	struct rusage_ext_tm *ruxtm2;
 	struct rusage_ext *rux2;
 {
 	register long *ip, *ip2;
@@ -967,9 +982,9 @@
 	rux->rux_uticks += rux2->rux_uticks;
 	rux->rux_sticks += rux2->rux_sticks;
 	rux->rux_iticks += rux2->rux_iticks;
-	rux->rux_uu += rux2->rux_uu;
-	rux->rux_su += rux2->rux_su;
-	rux->rux_tu += rux2->rux_tu;
+	ruxtm->rux_uu += ruxtm2->rux_uu;
+	ruxtm->rux_su += ruxtm2->rux_su;
+	ruxtm->rux_tu += ruxtm2->rux_tu;
 	if (ru->ru_maxrss < ru2->ru_maxrss)
 		ru->ru_maxrss = ru2->ru_maxrss;
 	ip = &ru->ru_first;
--- /usr/src/sys/kern/kern_synch.c	Fri Mar 23 01:37:54 2007
+++ kern_synch.c	Wed Apr 11 19:08:57 2007
@@ -364,13 +364,14 @@
 void
 mi_switch(int flags, struct thread *newtd)
 {
-	uint64_t new_switchtime;
-	struct thread *td;
+	uint64_t new_switchtime, calc_runtime;
+	struct thread *td, *td1;
 	struct proc *p;
 
 	mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
 	td = curthread;			/* XXX */
 	p = td->td_proc;		/* XXX */
+	calc_runtime = 0;
 	KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code"));
 #ifdef INVARIANTS
 	if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td))
@@ -401,15 +402,16 @@
 
 	/*
 	 * Compute the amount of time during which the current
-	 * process was running, and add that to its total so far.
+	 * process was running, and add that to the curthread total.
+	 * Cumulative adds will do the trick.
 	 */
 	new_switchtime = cpu_ticks();
-	p->p_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
-	p->p_rux.rux_uticks += td->td_uticks;
+	td->td_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
+	td->td_rux.rux_uticks += td->td_uticks;
 	td->td_uticks = 0;
-	p->p_rux.rux_iticks += td->td_iticks;
+	td->td_rux.rux_iticks += td->td_iticks;
 	td->td_iticks = 0;
-	p->p_rux.rux_sticks += td->td_sticks;
+	td->td_rux.rux_sticks += td->td_sticks;
 	td->td_sticks = 0;
 
 	td->td_generation++;	/* bump preempt-detect counter */
@@ -418,8 +420,11 @@
 	 * Check if the process exceeds its cpu resource allocation.  If
 	 * it reaches the max, arrange to kill the process in ast().
 	 */
+	FOREACH_THREAD_IN_PROC(p, td1)
+		calc_runtime += td1->td_rux.rux_runtime;
+
 	if (p->p_cpulimit != RLIM_INFINITY &&
-	    p->p_rux.rux_runtime >= p->p_cpulimit * cpu_tickrate()) {
+	    calc_runtime >= p->p_cpulimit * cpu_tickrate()) {
 		p->p_sflag |= PS_XCPU;
 		td->td_flags |= TDF_ASTPENDING;
 	}
--- /usr/src/sys/kern/kern_thread.c	Mon Apr  2 00:23:29 2007
+++ kern_thread.c	Thu Apr 12 00:28:23 2007
@@ -401,17 +401,22 @@
 
 	/* 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_uticks += td->td_uticks;
-	p->p_rux.rux_sticks += td->td_sticks;
-	p->p_rux.rux_iticks += td->td_iticks;
+	td->td_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
+	td->td_rux.rux_uticks += td->td_uticks;
+	td->td_rux.rux_sticks += td->td_sticks;
+	td->td_rux.rux_iticks += td->td_iticks;
 	PCPU_SET(switchtime, new_switchtime);
 	PCPU_SET(switchticks, ticks);
 	cnt.v_swtch++;
 
-	/* Add our usage into the usage of all our children. */
+	/*
+	 * Add our usage into the usage of all our children.  We don't need
+	 * to sum all the threads rusages beacause we assume we are the only
+	 * one thread present in the current proc.
+	 */
 	if (p->p_numthreads == 1)
-		ruadd(p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux);
+		ruadd(p->p_ru, &p->p_rux, &td->td_rux, &p->p_stats->p_cru,
+		    &p->p_crux, &td->td_crux);
 
 	/*
 	 * The last thread is left attached to the process
--- /usr/src/sys/kern/subr_trap.c	Thu Mar  8 05:34:06 2007
+++ subr_trap.c	Wed Apr 11 21:50:26 2007
@@ -145,7 +145,8 @@
 void
 ast(struct trapframe *framep)
 {
-	struct thread *td;
+	uint64_t calc_runtime;
+	struct thread *td, *td1;
 	struct proc *p;
 	struct rlimit rlim;
 	int sflag;
@@ -158,6 +159,7 @@
 
 	td = curthread;
 	p = td->td_proc;
+	calc_runtime = 0;
 
 	CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, p->p_pid,
             p->p_comm);
@@ -235,7 +237,9 @@
 		PROC_LOCK(p);
 		lim_rlimit(p, RLIMIT_CPU, &rlim);
 		mtx_lock_spin(&sched_lock);
-		if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) {
+		FOREACH_THREAD_IN_PROC(p, td1)
+			calc_runtime += td1->td_rux.rux_runtime;
+		if (calc_runtime >= rlim.rlim_max * cpu_tickrate()) {
 			mtx_unlock_spin(&sched_lock);
 			killproc(p, "exceeded maximum CPU limit");
 		} else {
--- /usr/src/sys/sys/proc.h	Fri Mar 23 01:37:56 2007
+++ proc.h	Thu Apr 12 00:27:14 2007
@@ -107,6 +107,19 @@
 	u_char	ar_args[1];	/* Arguments. */
 };
 
+struct rusage_ext {
+	u_int64_t	rux_runtime;    /* (cj) Real time. */
+	u_int64_t	rux_uticks;     /* (cj) Statclock hits in user mode. */
+	u_int64_t	rux_sticks;     /* (cj) Statclock hits in sys mode. */
+	u_int64_t	rux_iticks;     /* (cj) Statclock hits in intr mode. */
+};
+
+struct rusage_ext_tm {
+	u_int64_t	rux_uu;         /* (c) Previous user time in usec. */
+	u_int64_t	rux_su;         /* (c) Previous sys time in usec. */
+	u_int64_t	rux_tu;         /* (c) Previous total time in usec. */
+};
+
 /*-
  * Description of a process.
  *
@@ -270,6 +283,8 @@
 	int		td_xsig;	/* (c) Signal for ptrace */
 	u_long		td_profil_addr;	/* (k) Temporary addr until AST. */
 	u_int		td_profil_ticks; /* (k) Temporary ticks until AST. */
+	struct rusage_ext td_rux;	/* (cj) Internal resource usage. */
+	struct rusage_ext td_crux;	/* (c) Internal child resource usage. */
 	char		td_name[MAXCOMLEN + 1];	/* (*) Thread name. */
 #define	td_endzero td_base_pri
 
@@ -453,26 +468,6 @@
 #define	KUF_EXITING	0x00002		/* Upcall structure is exiting. */
 
 /*
- * XXX: Does this belong in resource.h or resourcevar.h instead?
- * Resource usage extension.  The times in rusage structs in the kernel are
- * never up to date.  The actual times are kept as runtimes and tick counts
- * (with control info in the "previous" times), and are converted when
- * userland asks for rusage info.  Backwards compatibility prevents putting
- * this directly in the user-visible rusage struct.
- *
- * Locking: (cj) means (j) for p_rux and (c) for p_crux.
- */
-struct rusage_ext {
-	u_int64_t	rux_runtime;    /* (cj) Real time. */
-	u_int64_t	rux_uticks;     /* (cj) Statclock hits in user mode. */
-	u_int64_t	rux_sticks;     /* (cj) Statclock hits in sys mode. */
-	u_int64_t	rux_iticks;     /* (cj) Statclock hits in intr mode. */
-	u_int64_t	rux_uu;         /* (c) Previous user time in usec. */
-	u_int64_t	rux_su;         /* (c) Previous sys time in usec. */
-	u_int64_t	rux_tu;         /* (c) Previous total time in usec. */
-};
-
-/*
  * The old fashionned process. May have multiple threads.
  *  Starts off with a single embedded THREAD.
  */
@@ -517,8 +512,8 @@
 	struct vmspace	*p_vmspace;	/* (b) Address space. */
 	u_int		p_swtime;	/* (j) Time swapped in or out. */
 	struct itimerval p_realtimer;	/* (c) Alarm timer. */
-	struct rusage_ext p_rux;	/* (cj) Internal resource usage. */
-	struct rusage_ext p_crux;	/* (c) Internal child resource usage. */
+	struct rusage_ext_tm p_rux;	/* (c) Internal resource usage. */
+	struct rusage_ext_tm p_crux;	/* (c) Internal child resource usage. */
 	int		p_profthreads;	/* (c) Num threads in addupc_task. */
 	int		p_maxthrwaits;	/* (c) Max threads num waiters */
 	int		p_traceflag;	/* (o) Kernel trace points. */
--- /usr/src/sys/sys/resourcevar.h	Wed Oct  4 07:24:43 2006
+++ resourcevar.h	Thu Apr 12 00:27:23 2007
@@ -102,6 +102,7 @@
 
 struct proc;
 struct rusage_ext;
+struct rusage_ext_tm;
 struct thread;
 
 void	 addupc_intr(struct thread *td, uintfptr_t pc, u_int ticks);
@@ -121,8 +122,9 @@
 	*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	 ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
-	    struct rusage_ext *rux2);
+void	 ruadd(struct rusage *ru, struct rusage_ext_tm *ruxtm,
+	    struct rusage_ext *rux, struct rusage *ru2,
+	    struct rusage_ext_tm *ruxtm2, struct rusage_ext *rux2);
 int	 suswintr(void *base, int word);
 struct uidinfo
 	*uifind(uid_t uid);
