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.

Requested by:	attilio [1]
Discussed with:	attilio, bde
Reviewed by:	bde
Based on submission by:	Alexander Krizhanovsky <ak natsys-lab com>
MFC after:	1 week
X-MFC-Note:	td_rux shall be moved to the end of struct thread
This commit is contained in:
Konstantin Belousov
2010-05-04 05:55:37 +00:00
parent 0c41a69e71
commit bed4c52416
5 changed files with 29 additions and 16 deletions
+24 -13
View File
@@ -76,7 +76,7 @@ static void calcru1(struct proc *p, struct rusage_ext *ruxp,
struct timeval *up, struct timeval *sp); struct timeval *up, struct timeval *sp);
static int donice(struct thread *td, struct proc *chgp, int n); static int donice(struct thread *td, struct proc *chgp, int n);
static struct uidinfo *uilookup(uid_t uid); 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. * Resource controls and accounting.
@@ -630,7 +630,7 @@ lim_cb(void *arg)
return; return;
PROC_SLOCK(p); PROC_SLOCK(p);
FOREACH_THREAD_IN_PROC(p, td) { FOREACH_THREAD_IN_PROC(p, td) {
ruxagg_tlock(p, td); ruxagg(p, td);
} }
PROC_SUNLOCK(p); PROC_SUNLOCK(p);
if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { 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) { FOREACH_THREAD_IN_PROC(p, td) {
if (td->td_incruntime == 0) if (td->td_incruntime == 0)
continue; continue;
ruxagg_tlock(p, td); ruxagg(p, td);
} }
calcru1(p, &p->p_rux, up, sp); 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); calccru(p, &rup->ru_utime, &rup->ru_stime);
break; 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: default:
error = EINVAL; 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. * Aggregate tick counts into the proc's rusage_ext.
*/ */
void void
ruxagg(struct rusage_ext *rux, struct thread *td) ruxagg_locked(struct rusage_ext *rux, struct thread *td)
{ {
THREAD_LOCK_ASSERT(td, MA_OWNED); 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_uticks += td->td_uticks;
rux->rux_sticks += td->td_sticks; rux->rux_sticks += td->td_sticks;
rux->rux_iticks += td->td_iticks; 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_incruntime = 0;
td->td_uticks = 0; td->td_uticks = 0;
td->td_iticks = 0; td->td_iticks = 0;
td->td_sticks = 0; td->td_sticks = 0;
}
static void
ruxagg_tlock(struct proc *p, struct thread *td)
{
thread_lock(td);
ruxagg(&p->p_rux, td);
thread_unlock(td); thread_unlock(td);
} }
@@ -1039,7 +1050,7 @@ rufetch(struct proc *p, struct rusage *ru)
*ru = p->p_ru; *ru = p->p_ru;
if (p->p_numthreads > 0) { if (p->p_numthreads > 0) {
FOREACH_THREAD_IN_PROC(p, td) { FOREACH_THREAD_IN_PROC(p, td) {
ruxagg_tlock(p, td); ruxagg(p, td);
rucollect(ru, &td->td_ru); rucollect(ru, &td->td_ru);
} }
} }
+1 -1
View File
@@ -432,7 +432,7 @@ thread_exit(void)
PROC_UNLOCK(p); PROC_UNLOCK(p);
thread_lock(td); thread_lock(td);
/* Save our tick information with both the thread and proc locked */ /* 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); PROC_SUNLOCK(p);
td->td_state = TDS_INACTIVE; td->td_state = TDS_INACTIVE;
#ifdef WITNESS #ifdef WITNESS
+2 -1
View File
@@ -240,7 +240,8 @@ struct thread {
u_int td_estcpu; /* (t) estimated cpu utilization */ u_int td_estcpu; /* (t) estimated cpu utilization */
int td_slptick; /* (t) Time at sleep. */ int td_slptick; /* (t) Time at sleep. */
int td_blktick; /* (t) Time spent blocked. */ 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_incruntime; /* (t) Cpu ticks to transfer to proc. */
uint64_t td_runtime; /* (t) How many cpu ticks we've run. */ uint64_t td_runtime; /* (t) How many cpu ticks we've run. */
u_int td_pticks; /* (t) Statclock hits for profiling */ u_int td_pticks; /* (t) Statclock hits for profiling */
+1
View File
@@ -56,6 +56,7 @@
#define RUSAGE_SELF 0 #define RUSAGE_SELF 0
#define RUSAGE_CHILDREN -1 #define RUSAGE_CHILDREN -1
#define RUSAGE_THREAD 1
struct rusage { struct rusage {
struct timeval ru_utime; /* user time used */ struct timeval ru_utime; /* user time used */
+1 -1
View File
@@ -131,7 +131,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 ruxagg(struct rusage_ext *rux, struct thread *td); void ruxagg_locked(struct rusage_ext *rux, struct thread *td);
int suswintr(void *base, int word); int suswintr(void *base, int word);
struct uidinfo struct uidinfo
*uifind(uid_t uid); *uifind(uid_t uid);