svn commit: r207468 - head/sys/kern

Kostik Belousov kostikbel at gmail.com
Sun May 2 15:52:49 UTC 2010


On Sun, May 02, 2010 at 03:48:50PM +0200, Attilio Rao wrote:
> 2010/5/1 Kostik Belousov <kostikbel at gmail.com>:
> > On Sat, May 01, 2010 at 04:47:36PM +0200, Attilio Rao wrote:
> >> 2010/5/1 Konstantin Belousov <kib at freebsd.org>:
> >> > Author: kib
> >> > Date: Sat May  1 14:46:17 2010
> >> > New Revision: 207468
> >> > URL: http://svn.freebsd.org/changeset/base/207468
> >> >
> >> > Log:
> >> >  Extract thread_lock()/ruxagg()/thread_unlock() fragment into utility
> >> >  function ruxagg_tlock().
> >> >  Convert the definition of kern_getrusage() to ANSI C.
> >> >
> >>
> >> I would have preferred a different naming for this, as the well known
> >> _locked version we have of many functions.
> >
> > But this is not the case there, because I did not renamed ruxagg().
> > It would be ruxagg()->ruxagg_unlocked() and ruxagg_tlock()->ruxagg().
> 
> Yes, this is exactly what I wanted to happen.
> 
> > My biggest question with the patch is I am not sure whether to apply
> > the same checks for tu in calctru() as it is done for tu in calcru1().
> > Any suggestions ?
> 
> I think that the checks may be present (the process-scope one is just
> an aggregate of the threads' one, thus the same conditions apply.

Ok, then the easiest way is to rewrite the patch. I removed your comments
for previous version since they are no longer relevant. I have to add
rusage_ext to struct thread, that would complicate the MFC.

And, looking at the whole picture, I do not understand how do we handle
the exiting threads. It seems that only user/system runtime is getting
collected to the process rusage. The other values, like i/o counters,
signals, ctx switches etc are thrown out.

diff --git a/lib/libc/sys/getrusage.2 b/lib/libc/sys/getrusage.2
index bdf5d45..423503f 100644
--- a/lib/libc/sys/getrusage.2
+++ b/lib/libc/sys/getrusage.2
@@ -28,7 +28,7 @@
 .\"     @(#)getrusage.2	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD$
 .\"
-.Dd June 4, 1993
+.Dd May 1, 2010
 .Dt GETRUSAGE 2
 .Os
 .Sh NAME
@@ -42,6 +42,7 @@
 .In sys/resource.h
 .Fd "#define	RUSAGE_SELF	 0"
 .Fd "#define	RUSAGE_CHILDREN	-1"
+.Fd "#define	RUSAGE_THREAD	1"
 .Ft int
 .Fn getrusage "int who" "struct rusage *rusage"
 .Sh DESCRIPTION
@@ -49,11 +50,12 @@ The
 .Fn getrusage
 system call
 returns information describing the resources utilized by the current
-process, or all its terminated child processes.
+thread, the current process, or all its terminated child processes.
 The
 .Fa who
 argument is either
-.Dv RUSAGE_SELF
+.Dv RUSAGE_THREAD ,
+.Dv RUSAGE_SELF ,
 or
 .Dv RUSAGE_CHILDREN .
 The buffer to which
@@ -175,6 +177,10 @@ The
 .Fn getrusage
 system call appeared in
 .Bx 4.2 .
+The
+.Dv RUSAGE_THREAD
+facility first appeared in
+.Fx 8.1 .
 .Sh BUGS
 There is no way to obtain information about a child process
 that has not yet terminated.
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index a3ed75d..0bc78d0 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -76,7 +76,7 @@ static void	calcru1(struct proc *p, struct rusage_ext *ruxp,
 		    struct timeval *up, struct timeval *sp);
 static int	donice(struct thread *td, struct proc *chgp, int n);
 static struct uidinfo *uilookup(uid_t uid);
-static void	ruxagg_tlock(struct proc *p, struct thread *td);
+static void	ruxagg(struct proc *p, struct thread *td);
 
 /*
  * Resource controls and accounting.
@@ -630,7 +630,7 @@ lim_cb(void *arg)
 		return;
 	PROC_SLOCK(p);
 	FOREACH_THREAD_IN_PROC(p, td) {
-		ruxagg_tlock(p, td);
+		ruxagg(p, td);
 	}
 	PROC_SUNLOCK(p);
 	if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) {
@@ -841,7 +841,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
 	FOREACH_THREAD_IN_PROC(p, td) {
 		if (td->td_incruntime == 0)
 			continue;
-		ruxagg_tlock(p, td);
+		ruxagg(p, td);
 	}
 	calcru1(p, &p->p_rux, up, sp);
 }
@@ -961,6 +961,16 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup)
 		calccru(p, &rup->ru_utime, &rup->ru_stime);
 		break;
 
+	case RUSAGE_THREAD:
+		PROC_SLOCK(p);
+		ruxagg(p, td);
+		PROC_SUNLOCK(p);
+		thread_lock(td);
+		*rup = td->td_ru;
+		calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime);
+		thread_unlock(td);
+		break;
+
 	default:
 		error = EINVAL;
 	}
@@ -1001,7 +1011,7 @@ ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
  * Aggregate tick counts into the proc's rusage_ext.
  */
 void
-ruxagg(struct rusage_ext *rux, struct thread *td)
+ruxagg_locked(struct rusage_ext *rux, struct thread *td)
 {
 
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
@@ -1010,18 +1020,19 @@ ruxagg(struct rusage_ext *rux, struct thread *td)
 	rux->rux_uticks += td->td_uticks;
 	rux->rux_sticks += td->td_sticks;
 	rux->rux_iticks += td->td_iticks;
-	td->td_incruntime = 0;
-	td->td_uticks = 0;
-	td->td_iticks = 0;
-	td->td_sticks = 0;
 }
 
 static void
-ruxagg_tlock(struct proc *p, struct thread *td)
+ruxagg(struct proc *p, struct thread *td)
 {
 
 	thread_lock(td);
-	ruxagg(&p->p_rux, td);
+	ruxagg_locked(&p->p_rux, td);
+	ruxagg_locked(&td->td_rux, td);
+	td->td_incruntime = 0;
+	td->td_uticks = 0;
+	td->td_iticks = 0;
+	td->td_sticks = 0;
 	thread_unlock(td);
 }
 
@@ -1039,7 +1050,7 @@ rufetch(struct proc *p, struct rusage *ru)
 	*ru = p->p_ru;
 	if (p->p_numthreads > 0)  {
 		FOREACH_THREAD_IN_PROC(p, td) {
-			ruxagg_tlock(p, td);
+			ruxagg(p, td);
 			rucollect(ru, &td->td_ru);
 		}
 	}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 9be4c2f..b32c584 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -432,7 +432,7 @@ thread_exit(void)
 	PROC_UNLOCK(p);
 	thread_lock(td);
 	/* Save our tick information with both the thread and proc locked */
-	ruxagg(&p->p_rux, td);
+	ruxagg_locked(&p->p_rux, td);
 	PROC_SUNLOCK(p);
 	td->td_state = TDS_INACTIVE;
 #ifdef WITNESS
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index fb31cfc..d2ff3df 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -173,6 +173,26 @@ struct kdtrace_thread;
 struct cpuset;
 
 /*
+ * 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. */
+};
+
+/*
  * Kernel runnable context (thread).
  * This is what is put to sleep and reactivated.
  * Thread context.  Processes may have multiple threads.
@@ -219,7 +239,8 @@ struct thread {
 	u_int		td_estcpu;	/* (t) estimated cpu utilization */
 	int		td_slptick;	/* (t) Time at sleep. */
 	int		td_blktick;	/* (t) Time spent blocked. */
-	struct rusage	td_ru;		/* (t) rusage information */
+	struct rusage	td_ru;		/* (t) rusage information. */
+	struct rusage_ext td_rux;	/* (t) Internal rusage information. */
 	uint64_t	td_incruntime;	/* (t) Cpu ticks to transfer to proc. */
 	uint64_t	td_runtime;	/* (t) How many cpu ticks we've run. */
 	u_int 		td_pticks;	/* (t) Statclock hits for profiling */
@@ -426,26 +447,6 @@ do {									\
 #define	TD_SET_CAN_RUN(td)	(td)->td_state = TDS_CAN_RUN
 
 /*
- * 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. */
-};
-
-/*
  * Process structure.
  */
 struct proc {
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
index 9af96af..e703744 100644
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -56,6 +56,7 @@
 
 #define	RUSAGE_SELF	0
 #define	RUSAGE_CHILDREN	-1
+#define	RUSAGE_THREAD	1
 
 struct rusage {
 	struct timeval ru_utime;	/* user time used */
diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
index 21728aa..95a9b49 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -131,7 +131,7 @@ void	 rucollect(struct rusage *ru, struct rusage *ru2);
 void	 rufetch(struct proc *p, struct rusage *ru);
 void	 rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
 	    struct timeval *sp);
-void	 ruxagg(struct rusage_ext *rux, struct thread *td);
+void	 ruxagg_locked(struct rusage_ext *rux, struct thread *td);
 int	 suswintr(void *base, int word);
 struct uidinfo
 	*uifind(uid_t uid);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/svn-src-all/attachments/20100502/fc22a1eb/attachment.pgp


More information about the svn-src-all mailing list