diff options
Diffstat (limited to 'sys/kern/kern_resource.c')
-rw-r--r-- | sys/kern/kern_resource.c | 192 |
1 files changed, 113 insertions, 79 deletions
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index e0a6655..d9e25c8 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <sys/resourcevar.h> #include <sys/sched.h> #include <sys/sx.h> +#include <sys/syscallsubr.h> #include <sys/sysent.h> #include <sys/time.h> @@ -67,6 +68,8 @@ static struct mtx uihashtbl_mtx; static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; static u_long uihash; /* size of hash table - 1 */ +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); @@ -691,65 +694,84 @@ getrlimit(td, uap) * system, and interrupt time usage. */ void -calcru(p, up, sp, ip) +calcru(p, up, sp) struct proc *p; struct timeval *up; struct timeval *sp; - struct timeval *ip; { - struct bintime bt, rt; - struct timeval tv; + struct bintime bt; + struct rusage_ext rux; struct thread *td; - /* {user, system, interrupt, total} {ticks, usec}; previous tu: */ - u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu; - int problemcase; + int bt_valid; - mtx_assert(&sched_lock, MA_OWNED); - /* XXX: why spl-protect ? worst case is an off-by-one report */ + PROC_LOCK_ASSERT(p, MA_OWNED); + mtx_assert(&sched_lock, MA_NOTOWNED); + bt_valid = 0; + mtx_lock_spin(&sched_lock); + rux = p->p_rux; + FOREACH_THREAD_IN_PROC(p, td) { + if (TD_IS_RUNNING(td)) { + /* + * Adjust for the current time slice. This is + * actually fairly important since the error here is + * on the order of a time quantum which is much + * greater than the precision of binuptime(). + */ + KASSERT(td->td_oncpu != NOCPU, + ("%s: running thread has no CPU", __func__)); + if (!bt_valid) { + binuptime(&bt); + bt_valid = 1; + } + bintime_add(&rux.rux_runtime, &bt); + bintime_sub(&rux.rux_runtime, + &pcpu_find(td->td_oncpu)->pc_switchtime); + } + } + mtx_unlock_spin(&sched_lock); + calcru1(p, &rux, up, sp); + p->p_rux.rux_uu = rux.rux_uu; + p->p_rux.rux_su = rux.rux_su; + p->p_rux.rux_iu = rux.rux_iu; +} - ut = p->p_uticks; - st = p->p_sticks; - it = p->p_iticks; +void +calccru(p, up, sp) + struct proc *p; + struct timeval *up; + struct timeval *sp; +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + calcru1(p, &p->p_crux, up, sp); +} + +static void +calcru1(p, ruxp, up, sp) + struct proc *p; + struct rusage_ext *ruxp; + struct timeval *up; + struct timeval *sp; +{ + struct timeval tv; + /* {user, system, interrupt, total} {ticks, usec}; previous tu: */ + u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu; + ut = ruxp->rux_uticks; + st = ruxp->rux_sticks; + it = ruxp->rux_iticks; tt = ut + st + it; if (tt == 0) { st = 1; tt = 1; } - rt = p->p_runtime; - problemcase = 0; - FOREACH_THREAD_IN_PROC(p, td) { - /* - * Adjust for the current time slice. This is actually fairly - * important since the error here is on the order of a time - * quantum, which is much greater than the sampling error. - */ - if (td == curthread) { - binuptime(&bt); - bintime_sub(&bt, PCPU_PTR(switchtime)); - bintime_add(&rt, &bt); - } else if (TD_IS_RUNNING(td)) { - /* - * XXX: this case should add the difference between - * the current time and the switch time as above, - * but the switch time is inaccessible, so we can't - * do the adjustment and will end up with a wrong - * runtime. A previous call with a different - * curthread may have obtained a (right or wrong) - * runtime that is in advance of ours. Just set a - * flag to avoid warning about this known problem. - */ - problemcase = 1; - } - } - bintime2timeval(&rt, &tv); + bintime2timeval(&ruxp->rux_runtime, &tv); tu = (u_int64_t)tv.tv_sec * 1000000 + tv.tv_usec; - ptu = p->p_uu + p->p_su + p->p_iu; + ptu = ruxp->rux_uu + ruxp->rux_su + ruxp->rux_iu; if (tu < ptu) { - if (!problemcase) - printf( + printf( "calcru: runtime went backwards from %ju usec to %ju usec for pid %d (%s)\n", - (uintmax_t)ptu, (uintmax_t)tu, p->p_pid, p->p_comm); + (uintmax_t)ptu, (uintmax_t)tu, p->p_pid, p->p_comm); tu = ptu; } if ((int64_t)tu < 0) { @@ -764,38 +786,34 @@ calcru(p, up, sp, ip) iu = tu - uu - su; /* Enforce monotonicity. */ - if (uu < p->p_uu || su < p->p_su || iu < p->p_iu) { - if (uu < p->p_uu) - uu = p->p_uu; - else if (uu + p->p_su + p->p_iu > tu) - uu = tu - p->p_su - p->p_iu; + if (uu < ruxp->rux_uu || su < ruxp->rux_su || iu < ruxp->rux_iu) { + if (uu < ruxp->rux_uu) + uu = ruxp->rux_uu; + else if (uu + ruxp->rux_su + ruxp->rux_iu > tu) + uu = tu - ruxp->rux_su - ruxp->rux_iu; if (st == 0) - su = p->p_su; + su = ruxp->rux_su; else { su = ((tu - uu) * st) / (st + it); - if (su < p->p_su) - su = p->p_su; - else if (uu + su + p->p_iu > tu) - su = tu - uu - p->p_iu; + if (su < ruxp->rux_su) + su = ruxp->rux_su; + else if (uu + su + ruxp->rux_iu > tu) + su = tu - uu - ruxp->rux_iu; } - KASSERT(uu + su + p->p_iu <= tu, + KASSERT(uu + su + ruxp->rux_iu <= tu, ("calcru: monotonisation botch 1")); iu = tu - uu - su; - KASSERT(iu >= p->p_iu, + KASSERT(iu >= ruxp->rux_iu, ("calcru: monotonisation botch 2")); } - p->p_uu = uu; - p->p_su = su; - p->p_iu = iu; + ruxp->rux_uu = uu; + ruxp->rux_su = su; + ruxp->rux_iu = iu; up->tv_sec = uu / 1000000; up->tv_usec = uu % 1000000; sp->tv_sec = su / 1000000; sp->tv_usec = su % 1000000; - if (ip != NULL) { - ip->tv_sec = iu / 1000000; - ip->tv_usec = iu % 1000000; - } } #ifndef _SYS_SYSPROTO_H_ @@ -807,51 +825,67 @@ struct getrusage_args { /* * MPSAFE */ -/* ARGSUSED */ int getrusage(td, uap) register struct thread *td; register struct getrusage_args *uap; { struct rusage ru; + int error; + + error = kern_getrusage(td, uap->who, &ru); + if (error == 0) + error = copyout(&ru, uap->rusage, sizeof(struct rusage)); + return (error); +} + +int +kern_getrusage(td, who, rup) + struct thread *td; + int who; + struct rusage *rup; +{ struct proc *p; p = td->td_proc; - switch (uap->who) { + PROC_LOCK(p); + switch (who) { case RUSAGE_SELF: - mtx_lock(&Giant); - mtx_lock_spin(&sched_lock); - calcru(p, &p->p_stats->p_ru.ru_utime, &p->p_stats->p_ru.ru_stime, - NULL); - mtx_unlock_spin(&sched_lock); - ru = p->p_stats->p_ru; - mtx_unlock(&Giant); + *rup = p->p_stats->p_ru; + calcru(p, &rup->ru_utime, &rup->ru_stime); break; case RUSAGE_CHILDREN: - mtx_lock(&Giant); - ru = p->p_stats->p_cru; - mtx_unlock(&Giant); + *rup = p->p_stats->p_cru; + calccru(p, &rup->ru_utime, &rup->ru_stime); break; default: + PROC_UNLOCK(p); return (EINVAL); - break; } - return (copyout(&ru, uap->rusage, sizeof(struct rusage))); + PROC_UNLOCK(p); + return (0); } void -ruadd(ru, ru2) +ruadd(ru, rux, ru2, rux2) struct rusage *ru; + struct rusage_ext *rux; struct rusage *ru2; + struct rusage_ext *rux2; { register long *ip, *ip2; register int i; - timevaladd(&ru->ru_utime, &ru2->ru_utime); - timevaladd(&ru->ru_stime, &ru2->ru_stime); + bintime_add(&rux->rux_runtime, &rux2->rux_runtime); + rux->rux_uticks += rux2->rux_uticks; + rux->rux_sticks += rux2->rux_sticks; + rux->rux_iticks += rux2->rux_iticks; + rux->rux_uu += rux2->rux_uu; + rux->rux_su += rux2->rux_su; + rux->rux_iu += rux2->rux_iu; if (ru->ru_maxrss < ru2->ru_maxrss) ru->ru_maxrss = ru2->ru_maxrss; ip = &ru->ru_first; |