Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Feb 2009 21:52:13 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r188764 - head/sys/kern
Message-ID:  <200902182152.n1ILqD9Q075752@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Wed Feb 18 21:52:13 2009
New Revision: 188764
URL: http://svn.freebsd.org/changeset/base/188764

Log:
  - Add a function (fill_kinfo_aggregate()) which aggregates relevant
    members for a kinfo entry on a process-wide system.
  - Use the newly introduced function in order to fix cases like
    KERN_PROC_PROC where aggregating stats are broken because they just
    consider the first thread in the pool for each process.
    (Note, additively, that KERN_PROC_PROC is rather inaccurate on
    thread-wide informations like the 'state' of the process.  Such
    informations should maybe be invalidated and being forceably discarded
    by the consumers?).
  - Simplify the logic of sysctl_out_proc() and adjust the
    fill_kinfo_thread() accordingly.
  - Remove checks on the FIRST_THREAD_IN_PROC() being NULL but add
    assertives.
  
  This patch should fix aggregate statistics for KERN_PROC_PROC.
  This is one of the reasons why top doesn't use this option and now it
  can be use it safely.
  ps, when launched in order to display just processes, now should report
  correct cpu utilization percentages and times (as opposed by the old
  code).
  
  Reviewed by:	jhb, emaste
  Sponsored by:	Sandvine Incorporated

Modified:
  head/sys/kern/kern_proc.c

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Wed Feb 18 21:12:48 2009	(r188763)
+++ head/sys/kern/kern_proc.c	Wed Feb 18 21:52:13 2009	(r188764)
@@ -115,6 +115,7 @@ MALLOC_DEFINE(M_SUBPROC, "subproc", "Pro
 
 static void doenterpgrp(struct proc *, struct pgrp *);
 static void orphanpg(struct pgrp *pg);
+static void fill_kinfo_aggregate(struct proc *p, struct kinfo_proc *kp);
 static void fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp);
 static void fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp,
     int preferthread);
@@ -670,6 +671,30 @@ DB_SHOW_COMMAND(pgrpdump, pgrpdump)
 #endif /* DDB */
 
 /*
+ * Calculate the kinfo_proc members which contain process-wide
+ * informations.
+ * Must be called with the target process locked.
+ */
+static void
+fill_kinfo_aggregate(struct proc *p, struct kinfo_proc *kp)
+{
+	struct thread *td;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+
+	kp->ki_estcpu = 0;
+	kp->ki_pctcpu = 0;
+	kp->ki_runtime = 0;
+	FOREACH_THREAD_IN_PROC(p, td) {
+		thread_lock(td);
+		kp->ki_pctcpu += sched_pctcpu(td);
+		kp->ki_runtime += cputick2usec(td->td_runtime);
+		kp->ki_estcpu += td->td_estcpu;
+		thread_unlock(td);
+	}
+}
+
+/*
  * Clear kinfo_proc and fill in any information that is common
  * to all threads in the process.
  * Must be called with the target process locked.
@@ -869,14 +894,15 @@ fill_kinfo_thread(struct thread *td, str
 	kp->ki_numthreads = p->p_numthreads;
 	kp->ki_pcb = td->td_pcb;
 	kp->ki_kstack = (void *)td->td_kstack;
-	kp->ki_pctcpu = sched_pctcpu(td);
-	kp->ki_estcpu = td->td_estcpu;
 	kp->ki_slptime = (ticks - td->td_slptick) / hz;
 	kp->ki_pri.pri_class = td->td_pri_class;
 	kp->ki_pri.pri_user = td->td_user_pri;
 
-	if (preferthread)
+	if (preferthread) {
 		kp->ki_runtime = cputick2usec(td->td_runtime);
+		kp->ki_pctcpu = sched_pctcpu(td);
+		kp->ki_estcpu = td->td_estcpu;
+	}
 
 	/* We can't get this anymore but ps etc never used it anyway. */
 	kp->ki_rqindex = 0;
@@ -894,9 +920,11 @@ void
 fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp)
 {
 
+	MPASS(FIRST_THREAD_IN_PROC(p) != NULL);
+
 	fill_kinfo_proc_only(p, kp);
-	if (FIRST_THREAD_IN_PROC(p) != NULL)
-		fill_kinfo_thread(FIRST_THREAD_IN_PROC(p), kp, 0);
+	fill_kinfo_thread(FIRST_THREAD_IN_PROC(p), kp, 0);
+	fill_kinfo_aggregate(p, kp);
 }
 
 struct pstats *
@@ -960,26 +988,20 @@ sysctl_out_proc(struct proc *p, struct s
 	pid_t pid = p->p_pid;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
+	MPASS(FIRST_THREAD_IN_PROC(p) != NULL);
 
-	fill_kinfo_proc_only(p, &kinfo_proc);
-	if (flags & KERN_PROC_NOTHREADS) {
-		if (FIRST_THREAD_IN_PROC(p) != NULL)
-			fill_kinfo_thread(FIRST_THREAD_IN_PROC(p),
-			    &kinfo_proc, 0);
+	fill_kinfo_proc(p, &kinfo_proc);
+	if (flags & KERN_PROC_NOTHREADS)
 		error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc,
-				   sizeof(kinfo_proc));
-	} else {
-		if (FIRST_THREAD_IN_PROC(p) != NULL)
-			FOREACH_THREAD_IN_PROC(p, td) {
-				fill_kinfo_thread(td, &kinfo_proc, 1);
-				error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc,
-						   sizeof(kinfo_proc));
-				if (error)
-					break;
-			}
-		else
+		    sizeof(kinfo_proc));
+	else {
+		FOREACH_THREAD_IN_PROC(p, td) {
+			fill_kinfo_thread(td, &kinfo_proc, 1);
 			error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc,
-					   sizeof(kinfo_proc));
+			    sizeof(kinfo_proc));
+			if (error)
+				break;
+		}
 	}
 	PROC_UNLOCK(p);
 	if (error)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902182152.n1ILqD9Q075752>