From c193de568b428d4159b2722b4962034cdcd3d36b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 11 May 2010 13:18:41 +0000 Subject: [PATCH] MFC r207468: Extract thread_lock()/ruxagg()/thread_unlock() fragment into utility function ruxagg_tlock(). Convert the definition of kern_getrusage() to ANSI C. MFC r207602: Implement RUSAGE_THREAD. Add td_rux to keep extended runtime and ticks information for thread to allow calcru1() (re)use. Rename ruxagg()->ruxagg_locked(), ruxagg_tlock()->ruxagg() [1]. The ruxagg_locked() function no longer clears thread ticks nor td_incruntime. Not an MFC: the td_rux is added to the end of struct thread to keep the KBI. Explicit bzero() of td_rux is added to new thread initialization points. --- sys/kern/kern_fork.c | 1 + sys/kern/kern_kthread.c | 1 + sys/kern/kern_resource.c | 40 ++++++++++++++++++++++++++-------------- sys/kern/kern_thr.c | 1 + sys/kern/kern_thread.c | 2 +- sys/sys/proc.h | 3 ++- sys/sys/resource.h | 1 + sys/sys/resourcevar.h | 2 +- 8 files changed, 34 insertions(+), 17 deletions(-) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 03d8cbc6bc1e..54402287453f 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -531,6 +531,7 @@ fork1(td, flags, pages, procp) bzero(&td2->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); + bzero(&td2->td_rux, sizeof(td2->td_rux)); bcopy(&td->td_startcopy, &td2->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 3c5248ebbb6e..f037ee7f4757 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -262,6 +262,7 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p, bzero(&newtd->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); + bzero(&newtd->td_rux, sizeof(newtd->td_rux)); /* XXX check if we should zero. */ bcopy(&oldtd->td_startcopy, &newtd->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index f86783959046..0bc78d0ae2ed 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -76,6 +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(struct proc *p, struct thread *td); /* * Resource controls and accounting. @@ -629,9 +630,7 @@ lim_cb(void *arg) return; PROC_SLOCK(p); FOREACH_THREAD_IN_PROC(p, td) { - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg(p, td); } PROC_SUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { @@ -842,9 +841,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp) FOREACH_THREAD_IN_PROC(p, td) { if (td->td_incruntime == 0) continue; - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg(p, td); } calcru1(p, &p->p_rux, up, sp); } @@ -945,10 +942,7 @@ getrusage(td, uap) } int -kern_getrusage(td, who, rup) - struct thread *td; - int who; - struct rusage *rup; +kern_getrusage(struct thread *td, int who, struct rusage *rup) { struct proc *p; int error; @@ -967,6 +961,16 @@ kern_getrusage(td, who, 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; } @@ -1007,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); @@ -1016,10 +1020,20 @@ 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; +} + +static void +ruxagg(struct proc *p, struct thread *td) +{ + + thread_lock(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); } /* @@ -1036,9 +1050,7 @@ rufetch(struct proc *p, struct rusage *ru) *ru = p->p_ru; if (p->p_numthreads > 0) { FOREACH_THREAD_IN_PROC(p, td) { - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg(p, td); rucollect(ru, &td->td_ru); } } diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 0b90dfc34067..d5d781585556 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -199,6 +199,7 @@ create_thread(struct thread *td, mcontext_t *ctx, bzero(&newtd->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); + bzero(&newtd->td_rux, sizeof(newtd->td_rux)); bcopy(&td->td_startcopy, &newtd->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); newtd->td_proc = td->td_proc; diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 7d3f759c8d97..e062aeab04b7 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 958ed86268a4..e2e66ccbee43 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -239,7 +239,7 @@ 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. */ 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 */ @@ -302,6 +302,7 @@ struct thread { int td_errno; /* Error returned by last syscall. */ struct vnet *td_vnet; /* (k) Effective vnet. */ const char *td_vnet_lpush; /* (k) Debugging vnet push / pop. */ + struct rusage_ext td_rux; /* (t) Internal rusage information. */ }; struct mtx *thread_lock_block(struct thread *); diff --git a/sys/sys/resource.h b/sys/sys/resource.h index 9af96afe0e01..e7037443246f 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 21728aa67e4b..95a9b49e1a6a 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);