diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-07-26 01:56:28 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-07-26 01:56:28 +0000 |
commit | 12738501a521de949783a0ef772f333a85a28079 (patch) | |
tree | a8d79b5579bc5fb4f0fe053219d7da149a912112 /sys/kern/kern_resource.c | |
parent | 58397ea88d58979fc9e046dc9c64692785b924ae (diff) |
Correct the links between threads, processes, pgrps, and sessions,
so that the process-level stuff is to/from struct process and not
struct proc. This fixes a bunch of problem cases in rthreads.
Based on earlier work by blambert and myself, but mostly written
at c2k10.
Tested by many: deraadt, sthen, krw, ray, and in snapshots
Diffstat (limited to 'sys/kern/kern_resource.c')
-rw-r--r-- | sys/kern/kern_resource.c | 92 |
1 files changed, 65 insertions, 27 deletions
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 9bf4e2eab72..76a078d9e03 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_resource.c,v 1.35 2010/06/29 20:14:46 guenther Exp $ */ +/* $OpenBSD: kern_resource.c,v 1.36 2010/07/26 01:56:27 guenther Exp $ */ /* $NetBSD: kern_resource.c,v 1.38 1996/10/23 07:19:38 matthias Exp $ */ /*- @@ -68,6 +68,7 @@ sys_getpriority(struct proc *curp, void *v, register_t *retval) syscallarg(int) which; syscallarg(id_t) who; } */ *uap = v; + struct process *pr; struct proc *p; int low = NZERO + PRIO_MAX + 1; @@ -75,25 +76,29 @@ sys_getpriority(struct proc *curp, void *v, register_t *retval) case PRIO_PROCESS: if (SCARG(uap, who) == 0) - p = curp; + pr = curp->p_p; else - p = pfind(SCARG(uap, who)); - if (p == 0) + pr = prfind(SCARG(uap, who)); + if (pr == NULL) break; - low = p->p_nice; + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + if (p->p_nice < low) + low = p->p_nice; + } break; case PRIO_PGRP: { struct pgrp *pg; if (SCARG(uap, who) == 0) - pg = curp->p_pgrp; + pg = curp->p_p->ps_pgrp; else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; - LIST_FOREACH(p, &pg->pg_members, p_pglist) { - if (p->p_nice < low) - low = p->p_nice; - } + LIST_FOREACH(pr, &pg->pg_members, ps_pglist) + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + if (p->p_nice < low) + low = p->p_nice; + } break; } @@ -124,19 +129,19 @@ sys_setpriority(struct proc *curp, void *v, register_t *retval) syscallarg(id_t) who; syscallarg(int) prio; } */ *uap = v; - struct proc *p; + struct process *pr; int found = 0, error = 0; switch (SCARG(uap, which)) { case PRIO_PROCESS: if (SCARG(uap, who) == 0) - p = curp; + pr = curp->p_p; else - p = pfind(SCARG(uap, who)); - if (p == 0) + pr = prfind(SCARG(uap, who)); + if (pr == NULL) break; - error = donice(curp, p, SCARG(uap, prio)); + error = donice(curp, pr, SCARG(uap, prio)); found++; break; @@ -144,25 +149,28 @@ sys_setpriority(struct proc *curp, void *v, register_t *retval) struct pgrp *pg; if (SCARG(uap, who) == 0) - pg = curp->p_pgrp; + pg = curp->p_p->ps_pgrp; else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; - LIST_FOREACH(p, &pg->pg_members, p_pglist) { - error = donice(curp, p, SCARG(uap, prio)); + LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { + error = donice(curp, pr, SCARG(uap, prio)); found++; } break; } - case PRIO_USER: + case PRIO_USER: { + struct proc *p; if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; LIST_FOREACH(p, &allproc, p_list) - if (p->p_ucred->cr_uid == SCARG(uap, who)) { - error = donice(curp, p, SCARG(uap, prio)); + if ((p->p_flag & P_THREAD) == 0 && + p->p_ucred->cr_uid == SCARG(uap, who)) { + error = donice(curp, p->p_p, SCARG(uap, prio)); found++; } break; + } default: return (EINVAL); @@ -173,25 +181,28 @@ sys_setpriority(struct proc *curp, void *v, register_t *retval) } int -donice(struct proc *curp, struct proc *chgp, int n) +donice(struct proc *curp, struct process *chgpr, int n) { struct pcred *pcred = curp->p_cred; + struct proc *p; int s; if (pcred->pc_ucred->cr_uid && pcred->p_ruid && - pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && - pcred->p_ruid != chgp->p_ucred->cr_uid) + pcred->pc_ucred->cr_uid != chgpr->ps_cred->pc_ucred->cr_uid && + pcred->p_ruid != chgpr->ps_cred->pc_ucred->cr_uid) return (EPERM); if (n > PRIO_MAX) n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; n += NZERO; - if (n < chgp->p_nice && suser(curp, 0)) + /* XXX wrong: p_nice should be in process */ + if (n < chgpr->ps_mainproc->p_nice && suser(curp, 0)) return (EACCES); - chgp->p_nice = n; + chgpr->ps_mainproc->p_nice = n; SCHED_LOCK(s); - (void)resetpriority(chgp); + TAILQ_FOREACH(p, &chgpr->ps_threads, p_thr_link) + (void)resetpriority(p); SCHED_UNLOCK(s); return (0); } @@ -364,13 +375,40 @@ sys_getrusage(struct proc *p, void *v, register_t *retval) syscallarg(int) who; syscallarg(struct rusage *) rusage; } */ *uap = v; + struct process *pr = p->p_p; + struct rusage ru; struct rusage *rup; switch (SCARG(uap, who)) { case RUSAGE_SELF: + calcru(p, &p->p_stats->p_ru.ru_utime, + &p->p_stats->p_ru.ru_stime, NULL); + ru = p->p_stats->p_ru; + rup = &ru; + + /* XXX add on already dead threads */ + + /* add on other living threads */ + { + struct proc *q; + + TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { + if (q == p || P_ZOMBIE(q)) + continue; + /* + * XXX this is approximate: no call + * to calcru in other running threads + */ + ruadd(rup, &q->p_stats->p_ru); + } + } + break; + + case RUSAGE_THREAD: rup = &p->p_stats->p_ru; calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); + ru = *rup; break; case RUSAGE_CHILDREN: |