[PATCH] Export per-thread resource usage via sysctl
John Baldwin
jhb at freebsd.org
Fri Jul 15 17:43:41 UTC 2011
This change exports each individual thread's resource usage via sysctl when
individual threads are requested via KERN_PROC_INC_THREAD. This generally
works correctly with 'top -m io' after the previous change to revert top(1)
back to using KERN_PROC_PROC when threads are not enabled. There is one issue
in that top doesn't necessarily DTRT when disabling/enabling threads via 'H'
at runtime while in io mode. I may do some further work to clean that up.
However, for just top run it will now show per-thread stats instead of
duplicating the per-process stats for each thread.
It also fixes a bug in that the code in calcru() to try to account for the
current thread's runtime wasn't correctly accounting charging that time to
the current thread.
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c (revision 224058)
+++ sys/kern/kern_proc.c (working copy)
@@ -848,6 +848,8 @@
kp->ki_tdaddr = td;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ if (preferthread)
+ PROC_SLOCK(p);
thread_lock(td);
if (td->td_wmesg != NULL)
strlcpy(kp->ki_wmesg, td->td_wmesg, sizeof(kp->ki_wmesg));
@@ -899,6 +901,7 @@
kp->ki_pri.pri_user = td->td_user_pri;
if (preferthread) {
+ rufetchtd(td, &kp->ki_rusage);
kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime);
kp->ki_pctcpu = sched_pctcpu(td);
kp->ki_estcpu = td->td_estcpu;
@@ -911,6 +914,8 @@
kp->ki_siglist = td->td_siglist;
kp->ki_sigmask = td->td_sigmask;
thread_unlock(td);
+ if (preferthread)
+ PROC_SUNLOCK(p);
}
/*
Index: sys/kern/kern_resource.c
===================================================================
--- sys/kern/kern_resource.c (revision 224058)
+++ sys/kern/kern_resource.c (working copy)
@@ -813,7 +813,7 @@
calcru(struct proc *p, struct timeval *up, struct timeval *sp)
{
struct thread *td;
- uint64_t u;
+ uint64_t runtime, u;
PROC_LOCK_ASSERT(p, MA_OWNED);
PROC_SLOCK_ASSERT(p, MA_OWNED);
@@ -826,7 +826,9 @@
td = curthread;
if (td->td_proc == p) {
u = cpu_ticks();
- p->p_rux.rux_runtime += u - PCPU_GET(switchtime);
+ runtime = u - PCPU_GET(switchtime);
+ td->td_runtime += runtime;
+ td->td_incruntime += runtime;
PCPU_SET(switchtime, u);
}
/* Make sure the per-thread stats are current. */
@@ -838,6 +840,34 @@
calcru1(p, &p->p_rux, up, sp);
}
+/* Collect resource usage for a single thread. */
+void
+rufetchtd(struct thread *td, struct rusage *ru)
+{
+ struct proc *p;
+ uint64_t runtime, u;
+
+ p = td->td_proc;
+ PROC_SLOCK_ASSERT(p, MA_OWNED);
+ THREAD_LOCK_ASSERT(td, MA_OWNED);
+ /*
+ * If we are getting stats for the current thread, then add in the
+ * stats that this thread has accumulated in its current time slice.
+ * We reset the thread and CPU state as if we had performed a context
+ * switch right here.
+ */
+ if (td == curthread) {
+ u = cpu_ticks();
+ runtime = u - PCPU_GET(switchtime);
+ td->td_runtime += runtime;
+ td->td_incruntime += runtime;
+ PCPU_SET(switchtime, u);
+ }
+ ruxagg(p, td);
+ *ru = td->td_ru;
+ calcru1(p, &td->td_rux, &ru->ru_utime, &ru->ru_stime);
+}
+
static void
calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
struct timeval *sp)
@@ -955,12 +985,10 @@
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);
+ rufetchtd(td, rup);
thread_unlock(td);
+ PROC_SUNLOCK(p);
break;
default:
Index: sys/sys/resourcevar.h
===================================================================
--- sys/sys/resourcevar.h (revision 224058)
+++ sys/sys/resourcevar.h (working copy)
@@ -136,6 +136,7 @@
void rufetch(struct proc *p, struct rusage *ru);
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
struct timeval *sp);
+void rufetchtd(struct thread *td, struct rusage *ru);
void ruxagg(struct proc *p, struct thread *td);
int suswintr(void *base, int word);
struct uidinfo
--
John Baldwin
More information about the freebsd-current
mailing list