Index: compat/svr4/svr4_misc.c =================================================================== RCS file: /usr/home/ncvs/src/sys/compat/svr4/svr4_misc.c,v retrieving revision 1.94 diff -u -p -r1.94 svr4_misc.c --- compat/svr4/svr4_misc.c 5 Jun 2007 00:00:50 -0000 1.94 +++ compat/svr4/svr4_misc.c 7 Jun 2007 20:53:39 -0000 @@ -1226,19 +1226,21 @@ loop: nfound++; + PROC_SLOCK(p); /* * See if we have a zombie. If so, WNOWAIT should be set, * as otherwise we should have called kern_wait() up above. */ if ((p->p_state == PRS_ZOMBIE) && ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) { + PROC_SUNLOCK(p); KASSERT(uap->options & SVR4_WNOWAIT, ("WNOWAIT is clear")); /* Found a zombie, so cache info in local variables. */ pid = p->p_pid; status = p->p_xstat; - ru = *p->p_ru; + ru = p->p_ru; calcru(p, &ru.ru_utime, &ru.ru_stime); PROC_UNLOCK(p); sx_sunlock(&proctree_lock); @@ -1253,7 +1255,6 @@ loop: * See if we have a stopped or continued process. * XXX: This duplicates the same code in kern_wait(). */ - PROC_SLOCK(p); if ((p->p_flag & P_STOPPED_SIG) && (p->p_suspcount == p->p_numthreads) && (p->p_flag & P_WAITED) == 0 && @@ -1264,7 +1265,7 @@ loop: sx_sunlock(&proctree_lock); pid = p->p_pid; status = W_STOPCODE(p->p_xstat); - ru = *p->p_ru; + ru = p->p_ru; calcru(p, &ru.ru_utime, &ru.ru_stime); PROC_UNLOCK(p); @@ -1285,7 +1286,7 @@ loop: if (((uap->options & SVR4_WNOWAIT)) == 0) p->p_flag &= ~P_CONTINUED; pid = p->p_pid; - ru = *p->p_ru; + ru = p->p_ru; status = SIGCONT; calcru(p, &ru.ru_utime, &ru.ru_stime); PROC_UNLOCK(p); Index: kern/init_main.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/init_main.c,v retrieving revision 1.278 diff -u -p -r1.278 init_main.c --- kern/init_main.c 5 Jun 2007 00:00:53 -0000 1.278 +++ kern/init_main.c 7 Jun 2007 20:53:45 -0000 @@ -497,6 +497,7 @@ proc0_post(void *dummy __unused) { struct timespec ts; struct proc *p; + struct rusage ru; /* * Now we can look at the time, having had a chance to verify the @@ -505,7 +506,11 @@ proc0_post(void *dummy __unused) sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { microuptime(&p->p_stats->p_start); + rufetch(p, &ru); /* Clears thread stats */ p->p_rux.rux_runtime = 0; + p->p_rux.rux_uticks = 0; + p->p_rux.rux_sticks = 0; + p->p_rux.rux_iticks = 0; } sx_sunlock(&allproc_lock); PCPU_SET(switchtime, cpu_ticks()); Index: kern/kern_exit.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/kern_exit.c,v retrieving revision 1.300 diff -u -p -r1.300 kern_exit.c --- kern/kern_exit.c 5 Jun 2007 00:00:53 -0000 1.300 +++ kern/kern_exit.c 7 Jun 2007 20:53:45 -0000 @@ -116,7 +116,6 @@ exit1(struct thread *td, int rv) struct ucred *tracecred; #endif struct plimit *plim; - struct rusage *ru; int locked; /* @@ -233,8 +232,6 @@ retry: */ EVENTHANDLER_INVOKE(process_exit, p); - MALLOC(ru, struct rusage *, sizeof(struct rusage), - M_ZOMBIE, M_WAITOK); /* * If parent is waiting for us to exit or exec, * P_PPWAIT is set; we will wakeup the parent below. @@ -447,16 +444,6 @@ retry: p->p_xstat = rv; p->p_xthread = td; /* - * All statistics have been aggregated into the final td_ru by - * thread_exit(). Copy these into the proc here where wait*() - * can find them. - * XXX We will miss any statistics gathered between here and - * thread_exit() except for those related to clock ticks. - */ - *ru = td->td_ru; - ru->ru_nvcsw++; - p->p_ru = ru; - /* * Notify interested parties of our demise. */ KNOTE_LOCKED(&p->p_klist, NOTE_EXIT); @@ -537,6 +524,11 @@ retry: knlist_destroy(&p->p_klist); /* + * Save our children's rusage information in our exit rusage. + */ + ruadd(&p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux); + + /* * Make sure the scheduler takes this thread out of its tables etc. * This will also release this thread's reference to the ucred. * Other thread parts to release include pcb bits and such. @@ -711,27 +703,15 @@ loop: } nfound++; + PROC_SLOCK(p); if (p->p_state == PRS_ZOMBIE) { - - /* - * It is possible that the last thread of this - * process is still running on another CPU - * in thread_exit() after having dropped the process - * lock via PROC_UNLOCK() but before it has completed - * cpu_throw(). In that case, the other thread must - * still hold the proc slock, so simply by acquiring - * proc slock once we will wait long enough for the - * thread to exit in that case. - * XXX This is questionable. - */ - PROC_SLOCK(p); 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; + *rusage = p->p_ru; calcru(p, &rusage->ru_utime, &rusage->ru_stime); } @@ -776,11 +756,9 @@ loop: p->p_xstat = 0; /* XXX: why? */ PROC_UNLOCK(p); PROC_LOCK(q); - ruadd(&q->p_stats->p_cru, &q->p_crux, p->p_ru, + ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, &p->p_rux); PROC_UNLOCK(q); - FREE(p->p_ru, M_ZOMBIE); - p->p_ru = NULL; /* * Decrement the count of procs running with this uid. @@ -822,7 +800,6 @@ loop: sx_xunlock(&allproc_lock); return (0); } - PROC_SLOCK(p); if ((p->p_flag & P_STOPPED_SIG) && (p->p_suspcount == p->p_numthreads) && (p->p_flag & P_WAITED) == 0 && Index: kern/kern_resource.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/kern_resource.c,v retrieving revision 1.174 diff -u -p -r1.174 kern_resource.c --- kern/kern_resource.c 5 Jun 2007 00:00:54 -0000 1.174 +++ kern/kern_resource.c 7 Jun 2007 20:53:45 -0000 @@ -1039,19 +1039,16 @@ rufetch(struct proc *p, struct rusage *r { struct thread *td; - 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)); + *ru = p->p_ru; + if (p->p_numthreads > 0) { FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); ruxagg(&p->p_rux, td); thread_unlock(td); rucollect(ru, &td->td_ru); } - } else - *ru = *p->p_ru; + } PROC_SUNLOCK(p); } Index: kern/kern_thread.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/kern_thread.c,v retrieving revision 1.247 diff -u -p -r1.247 kern_thread.c --- kern/kern_thread.c 4 Jun 2007 23:52:24 -0000 1.247 +++ kern/kern_thread.c 7 Jun 2007 20:53:45 -0000 @@ -391,9 +391,9 @@ thread_exit(void) PCPU_SET(switchtime, new_switchtime); PCPU_SET(switchticks, ticks); PCPU_INC(cnt.v_swtch); - /* Add the child usage to our own when the final thread exits. */ - if (p->p_numthreads == 1) - ruadd(p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux); + /* Save our resource usage in our process. */ + td->td_ru.ru_nvcsw++; + rucollect(&p->p_ru, &td->td_ru); /* * The last thread is left attached to the process * So that the whole bundle gets recycled. Skip @@ -411,9 +411,7 @@ thread_exit(void) thread_unlink(td); #endif thread_unlock(td); - /* Impart our resource usage on another thread */ td2 = FIRST_THREAD_IN_PROC(p); - rucollect(&td2->td_ru, &td->td_ru); sched_exit_thread(td2, td); /* @@ -462,7 +460,7 @@ thread_exit(void) } PROC_UNLOCK(p); thread_lock(td); - /* Aggregate our tick statistics into our parents rux. */ + /* Save our tick information with both the thread and proc locked */ ruxagg(&p->p_rux, td); PROC_SUNLOCK(p); td->td_state = TDS_INACTIVE; Index: sys/proc.h =================================================================== RCS file: /usr/home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.480 diff -u -p -r1.480 proc.h --- sys/proc.h 6 Jun 2007 03:40:47 -0000 1.480 +++ sys/proc.h 7 Jun 2007 20:53:51 -0000 @@ -572,7 +572,7 @@ struct proc { struct mdproc p_md; /* Any machine-dependent fields. */ struct callout p_itcallout; /* (h + c) Interval timer callout. */ u_short p_acflag; /* (c) Accounting flags. */ - struct rusage *p_ru; /* (a) Exit information. */ + struct rusage p_ru; /* (a) Exit information. */ struct proc *p_peers; /* (r) */ struct proc *p_leader; /* (b) */ void *p_emuldata; /* (c) Emulator state data. */