summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2011-07-18 17:33:08 +0000
committerjhb <jhb@FreeBSD.org>2011-07-18 17:33:08 +0000
commit4e1a6d0e6744fbd594114870804c3a5062815280 (patch)
treec9ca0ce831e01fabc0898005bf23fb41dcc1c5e9
parent9a6ff5ad378cfaaa99c5162e2b0f6e4cb6a3c796 (diff)
downloadFreeBSD-src-4e1a6d0e6744fbd594114870804c3a5062815280.zip
FreeBSD-src-4e1a6d0e6744fbd594114870804c3a5062815280.tar.gz
- Export each thread's individual resource usage in in struct kinfo_proc's
ki_rusage member when KERN_PROC_INC_THREAD is passed to one of the process sysctls. - Correctly account for the current thread's cputime in the thread when doing the runtime fixup in calcru(). - Use TIDs as the key to lookup the previous thread to compute IO stat deltas in IO mode in top when thread display is enabled. Reviewed by: kib Approved by: re (kib)
-rw-r--r--sys/kern/kern_proc.c5
-rw-r--r--sys/kern/kern_resource.c40
-rw-r--r--sys/sys/resourcevar.h1
-rw-r--r--usr.bin/top/machine.c17
4 files changed, 55 insertions, 8 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 4f1dc45..aac8b39 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -848,6 +848,8 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
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 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
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 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
kp->ki_siglist = td->td_siglist;
kp->ki_sigmask = td->td_sigmask;
thread_unlock(td);
+ if (preferthread)
+ PROC_SUNLOCK(p);
}
/*
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 1062703..78a25eb 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -813,7 +813,7 @@ void
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 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
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 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
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 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup)
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:
diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
index f17d95f..d091d85 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -136,6 +136,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 rufetchtd(struct thread *td, struct rusage *ru);
void ruxagg(struct proc *p, struct thread *td);
int suswintr(void *base, int word);
struct uidinfo
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 02dc847..1f8a002 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -235,6 +235,7 @@ static int *pcpu_cpu_states;
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
+static int compare_tid(const void *a, const void *b);
static const char *format_nice(const struct kinfo_proc *pp);
static void getsysctl(const char *name, void *ptr, size_t len);
static int swapmode(int *retavail, int *retfree);
@@ -557,7 +558,7 @@ get_old_proc(struct kinfo_proc *pp)
* cache it.
*/
oldpp = bsearch(&pp, previous_pref, previous_proc_count,
- sizeof(*previous_pref), compare_pid);
+ sizeof(*previous_pref), ps.thread ? compare_tid : compare_pid);
if (oldpp == NULL) {
pp->ki_udata = NOPROC;
return (NULL);
@@ -652,7 +653,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
previous_pref[i] = &previous_procs[i];
bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs));
qsort(previous_pref, nproc, sizeof(*previous_pref),
- compare_pid);
+ ps.thread ? compare_tid : compare_pid);
}
previous_proc_count = nproc;
@@ -1059,6 +1060,18 @@ compare_pid(const void *p1, const void *p2)
return ((*pp1)->ki_pid - (*pp2)->ki_pid);
}
+static int
+compare_tid(const void *p1, const void *p2)
+{
+ const struct kinfo_proc * const *pp1 = p1;
+ const struct kinfo_proc * const *pp2 = p2;
+
+ if ((*pp2)->ki_tid < 0 || (*pp1)->ki_tid < 0)
+ abort();
+
+ return ((*pp1)->ki_tid - (*pp2)->ki_tid);
+}
+
/*
* proc_compare - comparison function for "qsort"
* Compares the resource consumption of two processes using five
OpenPOWER on IntegriCloud