top(1) loses process user time count when threads end

John Baldwin jhb at freebsd.org
Tue Aug 16 13:50:53 UTC 2011


On Saturday, August 06, 2011 1:57:35 pm Yuri wrote:
> On 08/06/2011 02:11, Alexander Best wrote:
> > On Fri Aug  5 11, Yuri wrote:
> >> I have the process that first runs in 3 threads but later two active
> >> threads exit.
> >>
> >> top(1) shows this moment this way (1 sec intervals):
> >> 30833 yuri            3  76    0  4729M  4225M nanslp  4   0:32 88.62% app
> >> 30833 yuri            3  76    0  4729M  4225M nanslp  6   0:34 90.92% app
> >> 30833 yuri            1  96    0  4729M  4225M CPU1    1   0:03  1.17% app
> >> 30833 yuri            1  98    0  4729M  4226M CPU1    1   0:04 12.89% app
> >>
> >> Process time goes down: 0:34 ->  0:03. Also WCPU goes down 90.92% ->
> >> 1.17% even though this process is CPU bound and does intense things
> >> right after threads exit.
> >>
> >> getrusage(2) though, called in the process, shows the correct user time.
> >>
> >> I think this is the major bug in the process time accounting.
> > could you check, whether kern/128177 or kern/140892 describe your situation?
> 
> I have ULE scheduler. kern/128177 talks about single thread with ULE 
> scheduler, and my issue is with threads. So I am not sure if it is 
> related. There have been no motion on kern/128177 since Feb 9, 2009.
> kern/140892 is probably the same as mine.
> 
> In any case, both these PRs have to be fixed since they are very user 
> visible, not just some obscure issues.

You can try this perhaps:

Index: kern/kern_thread.c
===================================================================
--- kern/kern_thread.c	(revision 224879)
+++ kern/kern_thread.c	(working copy)
@@ -381,7 +381,7 @@
 void
 thread_exit(void)
 {
-	uint64_t new_switchtime;
+	uint64_t runtime, new_switchtime;
 	struct thread *td;
 	struct thread *td2;
 	struct proc *p;
@@ -410,15 +410,6 @@
 	 */
 	cpu_thread_exit(td);	/* XXXSMP */
 
-	/* Do the same timestamp bookkeeping that mi_switch() would do. */
-	new_switchtime = cpu_ticks();
-	p->p_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
-	PCPU_SET(switchtime, new_switchtime);
-	PCPU_SET(switchticks, ticks);
-	PCPU_INC(cnt.v_swtch);
-	/* 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
@@ -467,7 +458,21 @@
 		PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_OUT);
 #endif
 	PROC_UNLOCK(p);
+
+	/* Do the same timestamp bookkeeping that mi_switch() would do. */
+	new_switchtime = cpu_ticks();
+	runtime = new_switchtime - PCPU_GET(switchtime);
+	td->td_runtime += runtime;
+	td->td_incruntime += runtime;
+	PCPU_SET(switchtime, new_switchtime);
+	PCPU_SET(switchticks, ticks);
+	PCPU_INC(cnt.v_swtch);
+
+	/* Save our resource usage in our process. */
+	td->td_ru.ru_nvcsw++;
 	ruxagg(p, td);
+	rucollect(&p->p_ru, &td->td_ru);
+
 	thread_lock(td);
 	PROC_SUNLOCK(p);
 	td->td_state = TDS_INACTIVE;

-- 
John Baldwin


More information about the freebsd-hackers mailing list