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_proc.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_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 138 |
1 files changed, 74 insertions, 64 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 96276b58303..d609994c930 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.44 2010/07/19 23:00:15 guenther Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.45 2010/07/26 01:56:27 guenther Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -135,7 +135,7 @@ uid_find(uid_t uid) } /* - * Change the count associated with number of processes + * Change the count associated with number of threads * a given user is using. */ int @@ -154,17 +154,17 @@ chgproccnt(uid_t uid, int diff) * Is p an inferior of parent? */ int -inferior(struct proc *p, struct proc *parent) +inferior(struct process *pr, struct process *parent) { - for (; p != parent; p = p->p_pptr) - if (p->p_pid == 0 || p->p_pid == 1) + for (; pr != parent; pr = pr->ps_pptr) + if (pr->ps_pid == 0 || pr->ps_pid == 1) return (0); return (1); } /* - * Locate a process by number + * Locate a proc (thread) by number */ struct proc * pfind(pid_t pid) @@ -178,6 +178,20 @@ pfind(pid_t pid) } /* + * Locate a process by number + */ +struct process * +prfind(pid_t pid) +{ + struct proc *p; + + LIST_FOREACH(p, PIDHASH(pid), p_hash) + if (p->p_pid == pid) + return (p->p_flag & P_THREAD ? NULL : p->p_p); + return (NULL); +} + +/* * Locate a process group by number */ struct pgrp * @@ -195,9 +209,10 @@ pgfind(pid_t pgid) * Move p to a new or existing process group (and session) * Caller provides a pre-allocated pgrp and session that should * be freed if they are not used. + * XXX need proctree lock */ int -enterpgrp(struct proc *p, pid_t pgid, struct pgrp *newpgrp, +enterpgrp(struct process *pr, pid_t pgid, struct pgrp *newpgrp, struct session *newsess) { struct pgrp *pgrp = pgfind(pgid); @@ -205,52 +220,44 @@ enterpgrp(struct proc *p, pid_t pgid, struct pgrp *newpgrp, #ifdef DIAGNOSTIC if (pgrp != NULL && newsess) /* firewalls */ panic("enterpgrp: setsid into non-empty pgrp"); - if (SESS_LEADER(p)) + if (SESS_LEADER(pr)) panic("enterpgrp: session leader attempted setpgrp"); #endif if (pgrp == NULL) { - struct proc *np; /* * new process group */ #ifdef DIAGNOSTIC - if (p->p_pid != pgid) + if (pr->ps_pid != pgid) panic("enterpgrp: new pgrp and pid != pgid"); #endif - if ((np = pfind(p->p_pid)) == NULL || np != p) { - pool_put(&pgrp_pool, newpgrp); - if (newsess) - pool_put(&session_pool, newsess); - return (ESRCH); - } - pgrp = newpgrp; if (newsess) { /* * new session */ - newsess->s_leader = p; + newsess->s_leader = pr; newsess->s_count = 1; newsess->s_ttyvp = NULL; newsess->s_ttyp = NULL; - bcopy(p->p_session->s_login, newsess->s_login, + bcopy(pr->ps_session->s_login, newsess->s_login, sizeof(newsess->s_login)); - atomic_clearbits_int(&p->p_flag, P_CONTROLT); + atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT); pgrp->pg_session = newsess; #ifdef DIAGNOSTIC - if (p != curproc) - panic("enterpgrp: mksession and p != curproc"); + if (pr != curproc->p_p) + panic("enterpgrp: mksession but not curproc"); #endif } else { - pgrp->pg_session = p->p_session; + pgrp->pg_session = pr->ps_session; pgrp->pg_session->s_count++; } pgrp->pg_id = pgid; LIST_INIT(&pgrp->pg_members); LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); pgrp->pg_jobc = 0; - } else if (pgrp == p->p_pgrp) { + } else if (pgrp == pr->ps_pgrp) { if (newsess) pool_put(&session_pool, newsess); pool_put(&pgrp_pool, newpgrp); @@ -266,29 +273,28 @@ enterpgrp(struct proc *p, pid_t pgid, struct pgrp *newpgrp, * Increment eligibility counts before decrementing, otherwise we * could reach 0 spuriously during the first call. */ - fixjobc(p, pgrp, 1); - fixjobc(p, p->p_pgrp, 0); - - LIST_REMOVE(p, p_pglist); - if (LIST_EMPTY(&p->p_pgrp->pg_members)) - pgdelete(p->p_pgrp); - p->p_pgrp = pgrp; - LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); + fixjobc(pr, pgrp, 1); + fixjobc(pr, pr->ps_pgrp, 0); + + LIST_REMOVE(pr, ps_pglist); + if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) + pgdelete(pr->ps_pgrp); + pr->ps_pgrp = pgrp; + LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist); return (0); } /* * remove process from process group */ -int -leavepgrp(struct proc *p) +void +leavepgrp(struct process *pr) { - LIST_REMOVE(p, p_pglist); - if (LIST_EMPTY(&p->p_pgrp->pg_members)) - pgdelete(p->p_pgrp); - p->p_pgrp = 0; - return (0); + LIST_REMOVE(pr, ps_pglist); + if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) + pgdelete(pr->ps_pgrp); + pr->ps_pgrp = 0; } /* @@ -313,20 +319,21 @@ pgdelete(struct pgrp *pgrp) * process group of the same session). If that count reaches zero, the * process group becomes orphaned. Check both the specified process' * process group and that of its children. - * entering == 0 => p is leaving specified group. - * entering == 1 => p is entering specified group. + * entering == 0 => pr is leaving specified group. + * entering == 1 => pr is entering specified group. + * XXX need proctree lock */ void -fixjobc(struct proc *p, struct pgrp *pgrp, int entering) +fixjobc(struct process *pr, struct pgrp *pgrp, int entering) { struct pgrp *hispgrp; struct session *mysession = pgrp->pg_session; /* - * Check p's parent to see whether p qualifies its own process - * group; if so, adjust count for p's process group. + * Check pr's parent to see whether pr qualifies its own process + * group; if so, adjust count for pr's process group. */ - if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && + if ((hispgrp = pr->ps_pptr->ps_pgrp) != pgrp && hispgrp->pg_session == mysession) { if (entering) pgrp->pg_jobc++; @@ -339,10 +346,10 @@ fixjobc(struct proc *p, struct pgrp *pgrp, int entering) * their process groups; if so, adjust counts for children's * process groups. */ - LIST_FOREACH(p, &p->p_children, p_sibling) - if ((hispgrp = p->p_pgrp) != pgrp && + LIST_FOREACH(pr, &pr->ps_children, ps_sibling) + if ((hispgrp = pr->ps_pgrp) != pgrp && hispgrp->pg_session == mysession && - P_ZOMBIE(p) == 0) { + P_ZOMBIE(pr->ps_mainproc) == 0) { if (entering) hispgrp->pg_jobc++; else if (--hispgrp->pg_jobc == 0) @@ -358,13 +365,13 @@ fixjobc(struct proc *p, struct pgrp *pgrp, int entering) static void orphanpg(struct pgrp *pg) { - struct proc *p; + struct process *pr; - LIST_FOREACH(p, &pg->pg_members, p_pglist) { - if (p->p_stat == SSTOP) { - LIST_FOREACH(p, &pg->pg_members, p_pglist) { - psignal(p, SIGHUP); - psignal(p, SIGCONT); + LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { + if (pr->ps_mainproc->p_stat == SSTOP) { + LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { + prsignal(pr, SIGHUP); + prsignal(pr, SIGCONT); } return; } @@ -381,6 +388,7 @@ proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...)) char pstbuf[5]; const char *pst = pstbuf; + if (p->p_stat < 1 || p->p_stat > sizeof(pstat) / sizeof(pstat[0])) snprintf(pstbuf, sizeof(pstbuf), "%d", p->p_stat); else @@ -392,8 +400,8 @@ proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...)) p->p_priority, p->p_usrpri, p->p_nice); (*pr)(" forw=%p, list=%p,%p\n", TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); - (*pr)(" user=%p, vmspace=%p\n", - p->p_addr, p->p_vmspace); + (*pr)(" process=%p user=%p, vmspace=%p\n", + p->p_p, p->p_addr, p->p_vmspace); (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u%, swtime=%u\n", p->p_estcpu, p->p_cpticks, p->p_pctcpu / 100, p->p_pctcpu % 100, p->p_swtime); @@ -410,7 +418,8 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) { char *mode; int doingzomb = 0; - struct proc *p, *pp; + struct proc *p; + struct process *pr, *ppr; if (modif[0] == 0) modif[0] = 'n'; /* default == normal mode */ @@ -445,7 +454,8 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) } while (p != 0) { - pp = p->p_pptr; + pr = p->p_p; + ppr = pr->ps_pptr; if (p->p_stat) { db_printf("%c%5d ", p == curproc ? '*' : ' ', @@ -461,9 +471,9 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) case 'n': db_printf("%5d %5d %5d %d %#10x " "%-12.12s %-16s\n", - pp ? pp->p_pid : -1, - p->p_pgrp ? p->p_pgrp->pg_id : -1, - p->p_cred->p_ruid, p->p_stat, p->p_flag, + ppr ? ppr->ps_pid : -1, + pr->ps_pgrp ? pr->ps_pgrp->pg_id : -1, + pr->ps_cred->p_ruid, p->p_stat, p->p_flag, (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "", p->p_comm); break; @@ -491,7 +501,7 @@ void pgrpdump(void) { struct pgrp *pgrp; - struct proc *p; + struct process *pr; int i; for (i = 0; i <= pgrphash; i++) { @@ -502,9 +512,9 @@ pgrpdump(void) pgrp, pgrp->pg_id, pgrp->pg_session, pgrp->pg_session->s_count, LIST_FIRST(&pgrp->pg_members)); - LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { + LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { printf("\t\tpid %d addr %p pgrp %p\n", - p->p_pid, p, p->p_pgrp); + pr->ps_pid, pr, pr->ps_pgrp); } } } |