Changeset View
Standalone View
sys/kern/kern_racct.c
Show First 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
static uma_zone_t racct_zone; | static uma_zone_t racct_zone; | ||||
static void racct_sub_racct(struct racct *dest, const struct racct *src); | static void racct_sub_racct(struct racct *dest, const struct racct *src); | ||||
static void racct_sub_cred_locked(struct ucred *cred, int resource, | static void racct_sub_cred_locked(struct ucred *cred, int resource, | ||||
uint64_t amount); | uint64_t amount); | ||||
static void racct_add_cred_locked(struct ucred *cred, int resource, | static void racct_add_cred_locked(struct ucred *cred, int resource, | ||||
uint64_t amount); | uint64_t amount); | ||||
static int racct_set_locked(struct proc *p, int resource, uint64_t amount, | |||||
int force); | |||||
static void racct_updatepcpu_locked(struct proc *p); | |||||
static void racct_updatepcpu_racct_locked(struct racct *racct); | |||||
static void racct_updatepcpu_containers(void); | |||||
static void racct_propagatepcpu_locked(struct proc *p); | |||||
static void racct_settime_locked(struct proc *p, bool agg); | |||||
SDT_PROVIDER_DEFINE(racct); | SDT_PROVIDER_DEFINE(racct); | ||||
SDT_PROBE_DEFINE3(racct, , rusage, add, | SDT_PROBE_DEFINE3(racct, , rusage, add, | ||||
"struct proc *", "int", "uint64_t"); | "struct proc *", "int", "uint64_t"); | ||||
SDT_PROBE_DEFINE3(racct, , rusage, add__failure, | SDT_PROBE_DEFINE3(racct, , rusage, add__failure, | ||||
"struct proc *", "int", "uint64_t"); | "struct proc *", "int", "uint64_t"); | ||||
SDT_PROBE_DEFINE3(racct, , rusage, add__buf, | SDT_PROBE_DEFINE3(racct, , rusage, add__buf, | ||||
"struct proc *", "const struct buf *", "int"); | "struct proc *", "const struct buf *", "int"); | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | fixpt_t ccpu_exp[] = { | ||||
[108] = FSCALE * 0.00451658094261266798, | [108] = FSCALE * 0.00451658094261266798, | ||||
[109] = FSCALE * 0.00429630469075234057, | [109] = FSCALE * 0.00429630469075234057, | ||||
[110] = FSCALE * 0.00408677143846406699, | [110] = FSCALE * 0.00408677143846406699, | ||||
}; | }; | ||||
#endif | #endif | ||||
#define CCPU_EXP_MAX 110 | #define CCPU_EXP_MAX 110 | ||||
#if 0 | |||||
/* | /* | ||||
* This function is analogical to the getpcpu() function in the ps(1) command. | * This function is analogical to the getpcpu() function in the ps(1) command. | ||||
* They should both calculate in the same way so that the racct %cpu | * They should both calculate in the same way so that the racct %cpu | ||||
* calculations are consistent with the values showed by the ps(1) tool. | * calculations are consistent with the values showed by the ps(1) tool. | ||||
* The calculations are more complex in the 4BSD scheduler because of the value | * The calculations are more complex in the 4BSD scheduler because of the value | ||||
* of the ccpu variable. In ULE it is defined to be zero which saves us some | * of the ccpu variable. In ULE it is defined to be zero which saves us some | ||||
* work. | * work. | ||||
*/ | */ | ||||
Show All 37 Lines | #ifdef SMP | ||||
found = 0; | found = 0; | ||||
STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { | STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { | ||||
if (td == pc->pc_idlethread) { | if (td == pc->pc_idlethread) { | ||||
found = 1; | found = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (found) | if (found) | ||||
continue; | continue; | ||||
markj: This check needs to be carried forward to avoid accounting idle thread time in the host. Really… | |||||
#endif | #endif | ||||
thread_lock(td); | thread_lock(td); | ||||
#ifdef SCHED_4BSD | #ifdef SCHED_4BSD | ||||
pctcpu = sched_pctcpu(td); | pctcpu = sched_pctcpu(td); | ||||
/* Count also the yet unfinished second. */ | /* Count also the yet unfinished second. */ | ||||
pctcpu_next = (pctcpu * ccpu_exp[1]) >> FSHIFT; | pctcpu_next = (pctcpu * ccpu_exp[1]) >> FSHIFT; | ||||
pctcpu_next += sched_pctcpu_delta(td); | pctcpu_next += sched_pctcpu_delta(td); | ||||
p_pctcpu += max(pctcpu, pctcpu_next); | p_pctcpu += max(pctcpu, pctcpu_next); | ||||
Show All 12 Lines | |||||
#ifdef SCHED_4BSD | #ifdef SCHED_4BSD | ||||
if (swtime <= CCPU_EXP_MAX) | if (swtime <= CCPU_EXP_MAX) | ||||
return ((100 * (uint64_t)p_pctcpu * 1000000) / | return ((100 * (uint64_t)p_pctcpu * 1000000) / | ||||
(FSCALE - ccpu_exp[swtime])); | (FSCALE - ccpu_exp[swtime])); | ||||
#endif | #endif | ||||
return ((100 * (uint64_t)p_pctcpu * 1000000) / FSCALE); | return ((100 * (uint64_t)p_pctcpu * 1000000) / FSCALE); | ||||
} | } | ||||
#endif | |||||
static void | static void | ||||
racct_add_racct(struct racct *dest, const struct racct *src) | racct_add_racct(struct racct *dest, const struct racct *src) | ||||
{ | { | ||||
int i; | int i; | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
RACCT_LOCK_ASSERT(); | RACCT_LOCK_ASSERT(); | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | if (is_write) { | ||||
racct_add_locked(curproc, RACCT_WRITEIOPS, 1, 1); | racct_add_locked(curproc, RACCT_WRITEIOPS, 1, 1); | ||||
} else { | } else { | ||||
racct_add_locked(curproc, RACCT_READBPS, bp->b_bcount, 1); | racct_add_locked(curproc, RACCT_READBPS, bp->b_bcount, 1); | ||||
racct_add_locked(curproc, RACCT_READIOPS, 1, 1); | racct_add_locked(curproc, RACCT_READIOPS, 1, 1); | ||||
} | } | ||||
RACCT_UNLOCK(); | RACCT_UNLOCK(); | ||||
} | } | ||||
static void | |||||
racct_settime_locked(struct proc *p, bool agg) | |||||
{ | |||||
struct thread *td; | |||||
struct timeval wallclock; | |||||
uint64_t runtime; | |||||
ASSERT_RACCT_ENABLED(); | |||||
RACCT_LOCK_ASSERT(); | |||||
PROC_LOCK_ASSERT(p, MA_OWNED); | |||||
if (agg) { | |||||
PROC_STATLOCK(p); | |||||
FOREACH_THREAD_IN_PROC(p, td) | |||||
Not Done Inline ActionsComment style is either /* This comment fits on one line. */ or /* * Here is a somewhat longer comment, it needs to be broken up into two * lines. */ markj: Comment style is either
```
/* This comment fits on one line. */
```
or
```
/*
* Here is a… | |||||
ruxagg(p, td); | |||||
PROC_STATUNLOCK(p); | |||||
Not Done Inline ActionsI believe it is correct to perform the subtraction before calling cputick2usec(). It's a bit nicer to use only one call, especially since cputick2usec() contains a comparatively expensive division operation. markj: I believe it is correct to perform the subtraction before calling cputick2usec(). It's a bit… | |||||
} | |||||
runtime = cputick2usec(p->p_rux.rux_runtime); | |||||
Not Done Inline ActionsExtra newline after the closing brace. markj: Extra newline after the closing brace. | |||||
#ifdef notyet | |||||
KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime")); | |||||
#else | |||||
if (runtime < p->p_prev_runtime) | |||||
runtime = p->p_prev_runtime; | |||||
#endif | |||||
microuptime(&wallclock); | |||||
Not Done Inline ActionsHave you tried removing this ifdef to re-enable the KASSERT? I'm curious to know if it trips. markj: Have you tried removing this ifdef to re-enable the KASSERT? I'm curious to know if it trips. | |||||
Not Done Inline ActionsHmm, so p_prev_runtime is effectively unused now? Looks like we can just remove it. markj: Hmm, so `p_prev_runtime` is effectively unused now? Looks like we can just remove it. | |||||
timevalsub(&wallclock, &p->p_stats->p_start); | |||||
racct_set_locked(p, RACCT_CPU, runtime, 0); | |||||
racct_set_locked(p, RACCT_WALLCLOCK, | |||||
(uint64_t)wallclock.tv_sec * 1000000 + | |||||
wallclock.tv_usec, 0); | |||||
} | |||||
static int | static int | ||||
racct_set_locked(struct proc *p, int resource, uint64_t amount, int force) | racct_set_locked(struct proc *p, int resource, uint64_t amount, int force) | ||||
{ | { | ||||
int64_t old_amount, decayed_amount, diff_proc, diff_cred; | int64_t old_amount, diff_proc, diff_cred; | ||||
#ifdef RCTL | #ifdef RCTL | ||||
int error; | int error; | ||||
#endif | #endif | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
/* | /* | ||||
* We need proc lock to dereference p->p_ucred. | * We need proc lock to dereference p->p_ucred. | ||||
*/ | */ | ||||
PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | ||||
old_amount = p->p_racct->r_resources[resource]; | old_amount = p->p_racct->r_resources[resource]; | ||||
/* | /* | ||||
* The diffs may be negative. | * The diffs may be negative. | ||||
*/ | */ | ||||
diff_proc = amount - old_amount; | diff_proc = amount - old_amount; | ||||
#if 0 | |||||
if (resource == RACCT_PCTCPU) { | if (resource == RACCT_PCTCPU) { | ||||
/* | /* | ||||
* Resources in per-credential racct containers may decay. | * Resources in per-credential racct containers may decay. | ||||
* If this is the case, we need to calculate the difference | * If this is the case, we need to calculate the difference | ||||
* between the new amount and the proportional value of the | * between the new amount and the proportional value of the | ||||
* old amount that has decayed in the ucred racct containers. | * old amount that has decayed in the ucred racct containers. | ||||
*/ | */ | ||||
decayed_amount = old_amount * RACCT_DECAY_FACTOR / FSCALE; | decayed_amount = old_amount * RACCT_DECAY_FACTOR / FSCALE; | ||||
diff_cred = amount - decayed_amount; | diff_cred = amount - decayed_amount; | ||||
} else | } else | ||||
#endif | |||||
diff_cred = diff_proc; | diff_cred = diff_proc; | ||||
#ifdef notyet | #ifdef notyet | ||||
KASSERT(diff_proc >= 0 || RACCT_CAN_DROP(resource), | KASSERT(diff_proc >= 0 || RACCT_CAN_DROP(resource), | ||||
("%s: usage of non-droppable resource %d dropping", __func__, | ("%s: usage of non-droppable resource %d dropping", __func__, | ||||
resource)); | resource)); | ||||
#endif | #endif | ||||
#ifdef RCTL | #ifdef RCTL | ||||
if (diff_proc > 0) { | if (diff_proc > 0) { | ||||
▲ Show 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | #ifdef RCTL | ||||
RACCT_UNLOCK(); | RACCT_UNLOCK(); | ||||
PROC_UNLOCK(child); | PROC_UNLOCK(child); | ||||
#endif | #endif | ||||
} | } | ||||
void | void | ||||
racct_proc_exit(struct proc *p) | racct_proc_exit(struct proc *p) | ||||
{ | { | ||||
struct timeval wallclock; | |||||
uint64_t pct_estimate, pct, runtime; | |||||
int i; | int i; | ||||
if (!racct_enable) | if (!racct_enable) | ||||
return; | return; | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
/* | |||||
* We don't need to calculate rux, proc_reap() has already done this. | |||||
*/ | |||||
runtime = cputick2usec(p->p_rux.rux_runtime); | |||||
#ifdef notyet | |||||
KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime")); | |||||
#else | |||||
if (runtime < p->p_prev_runtime) | |||||
runtime = p->p_prev_runtime; | |||||
#endif | |||||
microuptime(&wallclock); | |||||
timevalsub(&wallclock, &p->p_stats->p_start); | |||||
if (wallclock.tv_sec > 0 || wallclock.tv_usec > 0) { | |||||
pct_estimate = (1000000 * runtime * 100) / | |||||
((uint64_t)wallclock.tv_sec * 1000000 + | |||||
wallclock.tv_usec); | |||||
} else | |||||
pct_estimate = 0; | |||||
pct = racct_getpcpu(p, pct_estimate); | |||||
RACCT_LOCK(); | RACCT_LOCK(); | ||||
racct_set_locked(p, RACCT_CPU, runtime, 0); | |||||
racct_add_cred_locked(p->p_ucred, RACCT_PCTCPU, pct); | |||||
racct_settime_locked(p, false); | |||||
racct_propagatepcpu_locked(p); | |||||
Not Done Inline ActionsCan this be removed? markj: Can this be removed? | |||||
KASSERT(p->p_racct->r_resources[RACCT_RSS] == 0, | KASSERT(p->p_racct->r_resources[RACCT_RSS] == 0, | ||||
("process reaped with %ju allocated for RSS\n", | ("process reaped with %ju allocated for RSS\n", | ||||
p->p_racct->r_resources[RACCT_RSS])); | p->p_racct->r_resources[RACCT_RSS])); | ||||
for (i = 0; i <= RACCT_MAX; i++) { | for (i = 0; i <= RACCT_MAX; i++) { | ||||
if (p->p_racct->r_resources[i] == 0) | if (p->p_racct->r_resources[i] == 0) | ||||
continue; | continue; | ||||
if (!RACCT_IS_RECLAIMABLE(i)) | if (!RACCT_IS_RECLAIMABLE(i)) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
racct_move(struct racct *dest, struct racct *src) | racct_move(struct racct *dest, struct racct *src) | ||||
{ | { | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
RACCT_LOCK(); | RACCT_LOCK(); | ||||
racct_add_racct(dest, src); | racct_add_racct(dest, src); | ||||
racct_sub_racct(src, src); | racct_sub_racct(src, src); | ||||
dest->r_runtime = src->r_runtime; | |||||
dest->r_time = src->r_time; | |||||
src->r_runtime = 0; | |||||
src->r_time = 0; | |||||
RACCT_UNLOCK(); | RACCT_UNLOCK(); | ||||
} | } | ||||
void | void | ||||
racct_proc_throttled(struct proc *p) | racct_proc_throttled(struct proc *p) | ||||
{ | { | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | if (p->p_throttled != 0) { | ||||
p->p_throttled = 0; | p->p_throttled = 0; | ||||
wakeup(p->p_racct); | wakeup(p->p_racct); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
racct_decay_callback(struct racct *racct, void *dummy1, void *dummy2) | racct_decay_callback(struct racct *racct, void *dummy1, void *dummy2) | ||||
{ | { | ||||
#if 0 | |||||
int64_t r_old, r_new; | int64_t r_old, r_new; | ||||
#endif | |||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
RACCT_LOCK_ASSERT(); | RACCT_LOCK_ASSERT(); | ||||
#ifdef RCTL | #ifdef RCTL | ||||
rctl_throttle_decay(racct, RACCT_READBPS); | rctl_throttle_decay(racct, RACCT_READBPS); | ||||
rctl_throttle_decay(racct, RACCT_WRITEBPS); | rctl_throttle_decay(racct, RACCT_WRITEBPS); | ||||
rctl_throttle_decay(racct, RACCT_READIOPS); | rctl_throttle_decay(racct, RACCT_READIOPS); | ||||
rctl_throttle_decay(racct, RACCT_WRITEIOPS); | rctl_throttle_decay(racct, RACCT_WRITEIOPS); | ||||
#endif | #endif | ||||
#if 0 | |||||
r_old = racct->r_resources[RACCT_PCTCPU]; | r_old = racct->r_resources[RACCT_PCTCPU]; | ||||
/* If there is nothing to decay, just exit. */ | /* If there is nothing to decay, just exit. */ | ||||
if (r_old <= 0) | if (r_old <= 0) | ||||
return; | return; | ||||
r_new = r_old * RACCT_DECAY_FACTOR / FSCALE; | r_new = r_old * RACCT_DECAY_FACTOR / FSCALE; | ||||
racct->r_resources[RACCT_PCTCPU] = r_new; | racct->r_resources[RACCT_PCTCPU] = r_new; | ||||
#endif | |||||
} | } | ||||
static void | static void | ||||
racct_decay_pre(void) | racct_decay_pre(void) | ||||
{ | { | ||||
RACCT_LOCK(); | RACCT_LOCK(); | ||||
} | } | ||||
Show All 15 Lines | ui_racct_foreach(racct_decay_callback, racct_decay_pre, | ||||
racct_decay_post, NULL, NULL); | racct_decay_post, NULL, NULL); | ||||
loginclass_racct_foreach(racct_decay_callback, racct_decay_pre, | loginclass_racct_foreach(racct_decay_callback, racct_decay_pre, | ||||
racct_decay_post, NULL, NULL); | racct_decay_post, NULL, NULL); | ||||
prison_racct_foreach(racct_decay_callback, racct_decay_pre, | prison_racct_foreach(racct_decay_callback, racct_decay_pre, | ||||
racct_decay_post, NULL, NULL); | racct_decay_post, NULL, NULL); | ||||
} | } | ||||
static void | static void | ||||
racct_updatepcpu_racct_locked(struct racct *racct) | |||||
{ | |||||
ASSERT_RACCT_ENABLED(); | |||||
RACCT_LOCK_ASSERT(); | |||||
Not Done Inline ActionsAssertions should come after local variable declarations. In general, local variable declarations always come first. markj: Assertions should come after local variable declarations. In general, local variable… | |||||
uint64_t runtime; | |||||
uint64_t elapsed; | |||||
uint64_t newpcpu; | |||||
uint64_t oldpcpu; | |||||
runtime = racct->r_resources[RACCT_CPU] - racct->r_runtime; | |||||
elapsed = racct->r_resources[RACCT_WALLCLOCK] - racct->r_time; | |||||
Not Done Inline ActionsA comment explaining this calculation would be warranted, I think. markj: A comment explaining this calculation would be warranted, I think. | |||||
if (elapsed == 0) { | |||||
Not Done Inline ActionsSame style nit here regarding comment style. markj: Same style nit here regarding comment style. | |||||
return; | |||||
} | |||||
newpcpu = runtime * 100 * 1000000 / elapsed; | |||||
Not Done Inline ActionsWhy do you need this check? markj: Why do you need this check? | |||||
oldpcpu = racct->r_resources[RACCT_PCTCPU]; | |||||
racct->r_resources[RACCT_PCTCPU] = ((FSCALE - RACCT_DECAY_FACTOR) * newpcpu + RACCT_DECAY_FACTOR * oldpcpu) / FSCALE; | |||||
racct->r_runtime = racct->r_resources[RACCT_CPU]; | |||||
racct->r_time = racct->r_resources[RACCT_WALLCLOCK]; | |||||
} | |||||
static void | |||||
racct_updatepcpu_locked(struct proc *p) | |||||
{ | |||||
ASSERT_RACCT_ENABLED(); | |||||
PROC_LOCK_ASSERT(p, MA_OWNED); | |||||
racct_updatepcpu_racct_locked(p->p_racct); | |||||
Not Done Inline ActionsThe multiplication on the RHS can overflow if mp_ncpus > 4, all three terms are 32 bits wide. Casting mp_ncpus to uint64_t before the multiplication should solve that. markj: The multiplication on the RHS can overflow if mp_ncpus > 4, all three terms are 32 bits wide. | |||||
} | |||||
static void | |||||
racct_propagatepcpu_locked(struct proc *p) | |||||
{ | |||||
struct prison *pr; | |||||
ASSERT_RACCT_ENABLED(); | |||||
PROC_LOCK_ASSERT(p, MA_OWNED); | |||||
racct_updatepcpu_racct_locked(p->p_ucred->cr_ruidinfo->ui_racct); | |||||
for (pr = p->p_ucred->cr_prison; pr != NULL; pr = pr->pr_parent) | |||||
racct_updatepcpu_racct_locked(pr->pr_prison_racct->prr_racct); | |||||
racct_updatepcpu_racct_locked(p->p_ucred->cr_loginclass->lc_racct); | |||||
} | |||||
static void | |||||
racct_updatepcpu_pre(void) | |||||
{ | |||||
RACCT_LOCK(); | |||||
} | |||||
static void | |||||
racct_updatepcpu_post(void) | |||||
{ | |||||
RACCT_UNLOCK(); | |||||
} | |||||
static void | |||||
racct_updatepcpu_racct_callback(struct racct *racct, void *dummy1, void *dummy2) | |||||
{ | |||||
racct_updatepcpu_racct_locked(racct); | |||||
} | |||||
#if 0 | |||||
static void | |||||
racct_updatepcpu_racct_callback_jail(struct racct *racct, void *dummy1, void *dummy2) | |||||
{ | |||||
printf("jail\n"); | |||||
racct_updatepcpu_racct_locked(racct); | |||||
} | |||||
static void | |||||
racct_updatepcpu_racct_callback_loginclass(struct racct *racct, void *dummy1, void *dummy2) | |||||
{ | |||||
printf("loginclass\n"); | |||||
racct_updatepcpu_racct_locked(racct); | |||||
} | |||||
static void | |||||
racct_updatepcpu_racct_callback_user(struct racct *racct, void *dummy1, void *dummy2) | |||||
{ | |||||
printf("user\n"); | |||||
racct_updatepcpu_racct_locked(racct); | |||||
} | |||||
#endif | |||||
static void | |||||
racct_updatepcpu_containers(void) | |||||
{ | |||||
ASSERT_RACCT_ENABLED(); | |||||
ui_racct_foreach(racct_updatepcpu_racct_callback, racct_updatepcpu_pre, | |||||
racct_updatepcpu_post, NULL, NULL); | |||||
loginclass_racct_foreach(racct_updatepcpu_racct_callback, racct_updatepcpu_pre, | |||||
racct_updatepcpu_post, NULL, NULL); | |||||
prison_racct_foreach(racct_updatepcpu_racct_callback, racct_updatepcpu_pre, | |||||
racct_updatepcpu_post, NULL, NULL); | |||||
} | |||||
static void | |||||
racctd(void) | racctd(void) | ||||
{ | { | ||||
struct thread *td; | |||||
struct proc *p; | struct proc *p; | ||||
struct timeval wallclock; | |||||
uint64_t pct, pct_estimate, runtime; | |||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
for (;;) { | for (;;) { | ||||
racct_decay(); | racct_decay(); | ||||
sx_slock(&allproc_lock); | sx_slock(&allproc_lock); | ||||
FOREACH_PROC_IN_SYSTEM(p) { | FOREACH_PROC_IN_SYSTEM(p) { | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
if (p->p_state != PRS_NORMAL) { | if (p->p_state != PRS_NORMAL) { | ||||
if (p->p_state == PRS_ZOMBIE) | if (p->p_state == PRS_ZOMBIE) | ||||
#if 0 | |||||
racct_set(p, RACCT_PCTCPU, 0); | racct_set(p, RACCT_PCTCPU, 0); | ||||
#endif | |||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
markjUnsubmitted Not Done Inline ActionsOh, be careful here. Despite the indentation, this is now if (p->p_state == PRS_ZOMBIE) PROC_UNLOCK(p); which is not right. markj: Oh, be careful here. Despite the indentation, this is now
```
if (p->p_state == PRS_ZOMBIE)… | |||||
continue; | continue; | ||||
} | } | ||||
microuptime(&wallclock); | |||||
timevalsub(&wallclock, &p->p_stats->p_start); | |||||
PROC_STATLOCK(p); | |||||
FOREACH_THREAD_IN_PROC(p, td) | |||||
ruxagg(p, td); | |||||
runtime = cputick2usec(p->p_rux.rux_runtime); | |||||
PROC_STATUNLOCK(p); | |||||
#ifdef notyet | |||||
KASSERT(runtime >= p->p_prev_runtime, | |||||
("runtime < p_prev_runtime")); | |||||
#else | |||||
if (runtime < p->p_prev_runtime) | |||||
runtime = p->p_prev_runtime; | |||||
#endif | |||||
p->p_prev_runtime = runtime; | |||||
if (wallclock.tv_sec > 0 || wallclock.tv_usec > 0) { | |||||
pct_estimate = (1000000 * runtime * 100) / | |||||
((uint64_t)wallclock.tv_sec * 1000000 + | |||||
wallclock.tv_usec); | |||||
} else | |||||
pct_estimate = 0; | |||||
pct = racct_getpcpu(p, pct_estimate); | |||||
RACCT_LOCK(); | RACCT_LOCK(); | ||||
#ifdef RCTL | #ifdef RCTL | ||||
rctl_throttle_decay(p->p_racct, RACCT_READBPS); | rctl_throttle_decay(p->p_racct, RACCT_READBPS); | ||||
rctl_throttle_decay(p->p_racct, RACCT_WRITEBPS); | rctl_throttle_decay(p->p_racct, RACCT_WRITEBPS); | ||||
rctl_throttle_decay(p->p_racct, RACCT_READIOPS); | rctl_throttle_decay(p->p_racct, RACCT_READIOPS); | ||||
rctl_throttle_decay(p->p_racct, RACCT_WRITEIOPS); | rctl_throttle_decay(p->p_racct, RACCT_WRITEIOPS); | ||||
#endif | #endif | ||||
racct_set_locked(p, RACCT_PCTCPU, pct, 1); | racct_settime_locked(p, true); | ||||
racct_set_locked(p, RACCT_CPU, runtime, 0); | racct_updatepcpu_locked(p); | ||||
racct_set_locked(p, RACCT_WALLCLOCK, | |||||
(uint64_t)wallclock.tv_sec * 1000000 + | |||||
wallclock.tv_usec, 0); | |||||
RACCT_UNLOCK(); | RACCT_UNLOCK(); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
/* | /* | ||||
* To ensure that processes are throttled in a fair way, we need | * To ensure that processes are throttled in a fair way, we need | ||||
* to iterate over all processes again and check the limits | * to iterate over all processes again and check the limits | ||||
* for %cpu resource only after ucred racct containers have been | * for %cpu resource only after ucred racct containers have been | ||||
Show All 11 Lines | FOREACH_PROC_IN_SYSTEM(p) { | ||||
pcpu_threshold) | pcpu_threshold) | ||||
racct_proc_throttle(p, -1); | racct_proc_throttle(p, -1); | ||||
} else if (p->p_throttled == -1) { | } else if (p->p_throttled == -1) { | ||||
racct_proc_wakeup(p); | racct_proc_wakeup(p); | ||||
} | } | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&allproc_lock); | ||||
racct_updatepcpu_containers(); | |||||
pause("-", hz); | pause("-", hz); | ||||
} | } | ||||
} | } | ||||
static struct kproc_desc racctd_kp = { | static struct kproc_desc racctd_kp = { | ||||
"racctd", | "racctd", | ||||
racctd, | racctd, | ||||
NULL | NULL | ||||
Show All 28 Lines |
This check needs to be carried forward to avoid accounting idle thread time in the host. Really it can be done much more simply:
I'm not sure why it was written this way to begin with, probably just oversight.
Idle threads live in a dedicated process (see idle_setup()). I think you can just change racctd to skip the process if it contains an idle thread. I would do it by adding code to the very beginning of racctd to store a pointer to STAILQ_FIRST(&cpuhead)->pc_idlethread->td_proc in a local variable. Then skip p if it's equal to that value.