- 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)
This commit is contained in:
parent
521ea19d1c
commit
2417d97ebb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=224188
@ -848,6 +848,8 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
|
|||||||
kp->ki_tdaddr = td;
|
kp->ki_tdaddr = td;
|
||||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||||
|
|
||||||
|
if (preferthread)
|
||||||
|
PROC_SLOCK(p);
|
||||||
thread_lock(td);
|
thread_lock(td);
|
||||||
if (td->td_wmesg != NULL)
|
if (td->td_wmesg != NULL)
|
||||||
strlcpy(kp->ki_wmesg, td->td_wmesg, sizeof(kp->ki_wmesg));
|
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;
|
kp->ki_pri.pri_user = td->td_user_pri;
|
||||||
|
|
||||||
if (preferthread) {
|
if (preferthread) {
|
||||||
|
rufetchtd(td, &kp->ki_rusage);
|
||||||
kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime);
|
kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime);
|
||||||
kp->ki_pctcpu = sched_pctcpu(td);
|
kp->ki_pctcpu = sched_pctcpu(td);
|
||||||
kp->ki_estcpu = td->td_estcpu;
|
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_siglist = td->td_siglist;
|
||||||
kp->ki_sigmask = td->td_sigmask;
|
kp->ki_sigmask = td->td_sigmask;
|
||||||
thread_unlock(td);
|
thread_unlock(td);
|
||||||
|
if (preferthread)
|
||||||
|
PROC_SUNLOCK(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -813,7 +813,7 @@ void
|
|||||||
calcru(struct proc *p, struct timeval *up, struct timeval *sp)
|
calcru(struct proc *p, struct timeval *up, struct timeval *sp)
|
||||||
{
|
{
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
uint64_t u;
|
uint64_t runtime, u;
|
||||||
|
|
||||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||||
PROC_SLOCK_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;
|
td = curthread;
|
||||||
if (td->td_proc == p) {
|
if (td->td_proc == p) {
|
||||||
u = cpu_ticks();
|
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);
|
PCPU_SET(switchtime, u);
|
||||||
}
|
}
|
||||||
/* Make sure the per-thread stats are current. */
|
/* 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);
|
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
|
static void
|
||||||
calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
|
calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
|
||||||
struct timeval *sp)
|
struct timeval *sp)
|
||||||
@ -955,12 +985,10 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup)
|
|||||||
|
|
||||||
case RUSAGE_THREAD:
|
case RUSAGE_THREAD:
|
||||||
PROC_SLOCK(p);
|
PROC_SLOCK(p);
|
||||||
ruxagg(p, td);
|
|
||||||
PROC_SUNLOCK(p);
|
|
||||||
thread_lock(td);
|
thread_lock(td);
|
||||||
*rup = td->td_ru;
|
rufetchtd(td, rup);
|
||||||
calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime);
|
|
||||||
thread_unlock(td);
|
thread_unlock(td);
|
||||||
|
PROC_SUNLOCK(p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -136,6 +136,7 @@ void rucollect(struct rusage *ru, struct rusage *ru2);
|
|||||||
void rufetch(struct proc *p, struct rusage *ru);
|
void rufetch(struct proc *p, struct rusage *ru);
|
||||||
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
|
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
|
||||||
struct timeval *sp);
|
struct timeval *sp);
|
||||||
|
void rufetchtd(struct thread *td, struct rusage *ru);
|
||||||
void ruxagg(struct proc *p, struct thread *td);
|
void ruxagg(struct proc *p, struct thread *td);
|
||||||
int suswintr(void *base, int word);
|
int suswintr(void *base, int word);
|
||||||
struct uidinfo
|
struct uidinfo
|
||||||
|
@ -235,6 +235,7 @@ static int *pcpu_cpu_states;
|
|||||||
|
|
||||||
static int compare_jid(const void *a, const void *b);
|
static int compare_jid(const void *a, const void *b);
|
||||||
static int compare_pid(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 const char *format_nice(const struct kinfo_proc *pp);
|
||||||
static void getsysctl(const char *name, void *ptr, size_t len);
|
static void getsysctl(const char *name, void *ptr, size_t len);
|
||||||
static int swapmode(int *retavail, int *retfree);
|
static int swapmode(int *retavail, int *retfree);
|
||||||
@ -557,7 +558,7 @@ get_old_proc(struct kinfo_proc *pp)
|
|||||||
* cache it.
|
* cache it.
|
||||||
*/
|
*/
|
||||||
oldpp = bsearch(&pp, previous_pref, previous_proc_count,
|
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) {
|
if (oldpp == NULL) {
|
||||||
pp->ki_udata = NOPROC;
|
pp->ki_udata = NOPROC;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -652,7 +653,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
|||||||
previous_pref[i] = &previous_procs[i];
|
previous_pref[i] = &previous_procs[i];
|
||||||
bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs));
|
bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs));
|
||||||
qsort(previous_pref, nproc, sizeof(*previous_pref),
|
qsort(previous_pref, nproc, sizeof(*previous_pref),
|
||||||
compare_pid);
|
ps.thread ? compare_tid : compare_pid);
|
||||||
}
|
}
|
||||||
previous_proc_count = nproc;
|
previous_proc_count = nproc;
|
||||||
|
|
||||||
@ -1059,6 +1060,18 @@ compare_pid(const void *p1, const void *p2)
|
|||||||
return ((*pp1)->ki_pid - (*pp2)->ki_pid);
|
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"
|
* proc_compare - comparison function for "qsort"
|
||||||
* Compares the resource consumption of two processes using five
|
* Compares the resource consumption of two processes using five
|
||||||
|
Loading…
Reference in New Issue
Block a user