Date: Wed, 20 Dec 2000 16:21:06 -0500 From: Jake Burkholder <jburkhol@home.com> To: smp@freebsd.org Subject: review: proctree_lock Message-ID: <20001220212106.41C6CBA7D@io.yi.org>
next in thread | raw e-mail | index | archive | help
This is a multipart MIME message. --==_Exmh_19954384880 Content-Type: text/plain; charset=us-ascii Attached is a patch that adds the proctree_lock. This is a lockmgr lock which protects all parent-child relationships between processes. Specifically the field p_pptr, and the p_children/p_sibling list. Dependant functions are proc_reparent(), and stop(). proc_reparent requires an exclusive hold, stop requires at least a shared hold. This will allow several of the trivial proc-related system calls to be made MP-safe. Please review and test it. --==_Exmh_19954384880 Content-Type: text/plain ; name="proctree.diff"; charset=us-ascii Content-Description: proctree.diff Content-Disposition: attachment; filename="proctree.diff" Index: alpha/alpha/sys_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/sys_machdep.c,v retrieving revision 1.7 diff -u -r1.7 sys_machdep.c --- alpha/alpha/sys_machdep.c 2000/01/16 07:07:28 1.7 +++ alpha/alpha/sys_machdep.c 2000/12/18 00:56:24 @@ -173,6 +173,7 @@ if (error) return (error); + PROCTREE_LOCK(PT_SHARED); if (p->p_pptr) { s = splimp(); if (p->p_pptr) { @@ -182,6 +183,7 @@ error = ESRCH; splx(s); } + PROCTREE_LOCK(PT_RELEASE); return error; } @@ -192,6 +194,7 @@ unsigned long uac; error = ESRCH; + PROCTREE_LOCK(PT_SHARED); if (p->p_pptr) { s = splimp(); if (p->p_pptr) { @@ -200,5 +203,6 @@ } splx(s); } + PROCTREE_LOCK(PT_RELEASE); return error; } Index: alpha/alpha/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/vm_machdep.c,v retrieving revision 1.39 diff -u -r1.39 vm_machdep.c --- alpha/alpha/vm_machdep.c 2000/12/01 18:55:58 1.39 +++ alpha/alpha/vm_machdep.c 2000/12/20 20:56:07 @@ -256,6 +256,18 @@ mtx_enter(&sched_lock, MTX_SPIN); mtx_exit(&Giant, MTX_DEF | MTX_NOSWITCH); mtx_assert(&Giant, MA_NOTOWNED); + + /* + * We have to wait until after releasing all locks before + * changing p_stat. If we block on a mutex while waiting to + * release the allproc_lock, then we will be back at SRUN when + * we resume here and our parent will never harvest us. + */ + p->p_stat = SZOMB; + + mp_fixme("assumption: p_pptr won't change at this time"); + wakeup(p->p_pptr); + cnt.v_swtch++; cpu_switch(); panic("cpu_exit"); Index: compat/linprocfs/linprocfs_misc.c =================================================================== RCS file: /home/ncvs/src/sys/compat/linprocfs/linprocfs_misc.c,v retrieving revision 1.16 diff -u -r1.16 linprocfs_misc.c --- compat/linprocfs/linprocfs_misc.c 2000/12/13 20:22:24 1.16 +++ compat/linprocfs/linprocfs_misc.c 2000/12/18 01:33:30 @@ -364,14 +364,18 @@ struct sbuf sb; char *ps; int r, xlen; + pid_t ppid; + PROCTREE_LOCK(PT_SHARED); + ppid = p->p_pptr ? p->p_pptr->p_pid : 0; + PROCTREE_LOCK(PT_RELEASE); fill_kinfo_proc(p, &kp); sbuf_new(&sb, NULL, 1024, 0); sbuf_printf(&sb, "%d", p->p_pid); #define PS_ADD(name, fmt, arg) sbuf_printf(&sb, " " fmt, arg) PS_ADD("comm", "(%s)", p->p_comm); PS_ADD("statr", "%c", '0'); /* XXX */ - PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); + PS_ADD("ppid", "%d", ppid); PS_ADD("pgrp", "%d", p->p_pgid); PS_ADD("session", "%d", p->p_session->s_sid); PS_ADD("tty", "%d", 0); /* XXX */ @@ -447,6 +451,7 @@ char *state; int i, r, xlen; segsz_t lsize; + pid_t ppid; sbuf_new(&sb, NULL, 1024, 0); @@ -457,6 +462,9 @@ state = state_str[(int)p->p_stat]; mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_SHARED); + ppid = p->p_pptr ? p->p_pptr->p_pid : 0; + PROCTREE_LOCK(PT_RELEASE); fill_kinfo_proc(p, &kp); sbuf_printf(&sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ sbuf_printf(&sb, "State:\t%s\n", state); @@ -465,7 +473,7 @@ * Credentials */ sbuf_printf(&sb, "Pid:\t%d\n", p->p_pid); - sbuf_printf(&sb, "PPid:\t%d\n", p->p_pptr ? p->p_pptr->p_pid : 0); + sbuf_printf(&sb, "PPid:\t%d\n", ppid); sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_cred->p_ruid, p->p_ucred->cr_uid, p->p_cred->p_svuid, Index: compat/svr4/svr4_misc.c =================================================================== RCS file: /home/ncvs/src/sys/compat/svr4/svr4_misc.c,v retrieving revision 1.17 diff -u -r1.17 svr4_misc.c --- compat/svr4/svr4_misc.c 2000/12/13 00:16:59 1.17 +++ compat/svr4/svr4_misc.c 2000/12/18 01:40:53 @@ -1205,6 +1205,7 @@ loop: nfound = 0; + PROCTREE_LOCK(PT_SHARED); for (q = p->p_children.lh_first; q != 0; q = q->p_sibling.le_next) { if (SCARG(uap, id) != WAIT_ANY && q->p_pid != SCARG(uap, id) && @@ -1216,6 +1217,7 @@ nfound++; if (q->p_stat == SZOMB && ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)))) { + PROCTREE_LOCK(PT_RELEASE); *retval = 0; DPRINTF(("found %d\n", q->p_pid)); if ((error = svr4_setinfo(q, q->p_xstat, @@ -1236,14 +1238,18 @@ * parent a SIGCHLD. The rest of the cleanup will be * done when the old parent waits on the child. */ - if ((q->p_flag & P_TRACED) && - q->p_oppid != q->p_pptr->p_pid) { - t = pfind(q->p_oppid); - proc_reparent(q, t ? t : initproc); - q->p_oppid = 0; - q->p_flag &= ~(P_TRACED | P_WAITED); - wakeup((caddr_t)q->p_pptr); - return 0; + if (q->p_flag & P_TRACED) { + PROCTREE_LOCK(PT_EXCLUSIVE); + if (q->p_oppid != q->p_pptr->p_pid) { + t = pfind(q->p_oppid); + proc_reparent(q, t ? t : initproc); + q->p_oppid = 0; + q->p_flag &= ~(P_TRACED | P_WAITED); + wakeup((caddr_t)q->p_pptr); + PROCTREE_LOCK(PT_RELEASE); + return 0; + } + PROCTREE_LOCK(PT_RELEASE); } q->p_xstat = 0; ruadd(&p->p_stats->p_cru, q->p_ru); @@ -1260,7 +1266,9 @@ LIST_REMOVE(q, p_list); /* off zombproc */ ALLPROC_LOCK(AP_RELEASE); + PROCTREE_LOCK(PT_EXCLUSIVE); LIST_REMOVE(q, p_sibling); + PROCTREE_LOCK(PT_RELEASE); /* * Decrement the count of procs running with this uid. Index: i386/i386/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v retrieving revision 1.145 diff -u -r1.145 vm_machdep.c --- i386/i386/vm_machdep.c 2000/12/08 21:50:09 1.145 +++ i386/i386/vm_machdep.c 2000/12/20 20:56:38 @@ -259,6 +259,18 @@ mtx_enter(&sched_lock, MTX_SPIN); mtx_exit(&Giant, MTX_DEF | MTX_NOSWITCH); mtx_assert(&Giant, MA_NOTOWNED); + + /* + * We have to wait until after releasing all locks before + * changing p_stat. If we block on a mutex while waiting to + * release the allproc_lock, then we will be back at SRUN when + * we resume here and our parent will never harvest us. + */ + p->p_stat = SZOMB; + + mp_fixme("assumption: p_pptr won't change at this time"); + wakeup(p->p_pptr); + cnt.v_swtch++; cpu_throw(); panic("cpu_exit"); Index: ia64/ia64/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia64/vm_machdep.c,v retrieving revision 1.9 diff -u -r1.9 vm_machdep.c --- ia64/ia64/vm_machdep.c 2000/11/15 19:44:38 1.9 +++ ia64/ia64/vm_machdep.c 2000/12/20 20:51:19 @@ -306,6 +306,18 @@ mtx_enter(&sched_lock, MTX_SPIN); mtx_exit(&Giant, MTX_DEF | MTX_NOSWITCH); mtx_assert(&Giant, MA_NOTOWNED); + + /* + * We have to wait until after releasing all locks before + * changing p_stat. If we block on a mutex then we will be + * back at SRUN when we resume and our parent will never + * harvest us. + */ + p->p_stat = SZOMB; + + mp_fixme("assumption: p_pptr won't change at this time"); + wakeup(p->p_pptr); + cnt.v_swtch++; cpu_switch(); panic("cpu_exit"); Index: kern/kern_exec.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v retrieving revision 1.120 diff -u -r1.120 kern_exec.c --- kern/kern_exec.c 2000/11/30 21:06:05 1.120 +++ kern/kern_exec.c 2000/12/18 00:57:06 @@ -267,10 +267,12 @@ * it that it now has its own resources back */ p->p_flag |= P_EXEC; + PROCTREE_LOCK(PT_SHARED); if (p->p_pptr && (p->p_flag & P_PPWAIT)) { p->p_flag &= ~P_PPWAIT; wakeup((caddr_t)p->p_pptr); } + PROCTREE_LOCK(PT_RELEASE); /* * Implement image setuid/setgid. Index: kern/kern_exit.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exit.c,v retrieving revision 1.111 diff -u -r1.111 kern_exit.c --- kern/kern_exit.c 2000/12/18 07:10:04 1.111 +++ kern/kern_exit.c 2000/12/20 20:53:54 @@ -267,17 +267,10 @@ ALLPROC_LOCK(AP_EXCLUSIVE); LIST_REMOVE(p, p_list); LIST_INSERT_HEAD(&zombproc, p, p_list); - LIST_REMOVE(p, p_hash); ALLPROC_LOCK(AP_RELEASE); - /* - * We have to wait until after releasing this lock before - * changing p_stat. If we block on a mutex while waiting to - * release the allproc_lock, then we will be back at SRUN when - * we resume here and our parent will never harvest us. - */ - p->p_stat = SZOMB; + PROCTREE_LOCK(PT_EXCLUSIVE); q = LIST_FIRST(&p->p_children); if (q) /* only need this if any child is S_ZOMB */ wakeup((caddr_t) initproc); @@ -343,7 +336,7 @@ psignal(p->p_pptr, SIGCHLD); } - wakeup((caddr_t)p->p_pptr); + PROCTREE_LOCK(PT_RELEASE); /* * Clear curproc after we've done all operations * that could block, and before tearing down the rest @@ -419,6 +412,7 @@ return (EINVAL); loop: nfound = 0; + PROCTREE_LOCK(PT_SHARED); LIST_FOREACH(p, &q->p_children, p_sibling) { if (uap->pid != WAIT_ANY && p->p_pid != uap->pid && p->p_pgid != -uap->pid) @@ -440,6 +434,7 @@ mtx_enter(&sched_lock, MTX_SPIN); if (p->p_stat == SZOMB) { mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); /* charge childs scheduling cpu usage to parent */ if (curproc->p_pid != 1) { @@ -466,12 +461,17 @@ * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. */ - if (p->p_oppid && (t = pfind(p->p_oppid))) { - p->p_oppid = 0; - proc_reparent(p, t); - psignal(t, SIGCHLD); - wakeup((caddr_t)t); - return (0); + if (p->p_oppid) { + PROCTREE_LOCK(PT_EXCLUSIVE); + if ((t = pfind(p->p_oppid)) != NULL) { + p->p_oppid = 0; + proc_reparent(p, t); + psignal(t, SIGCHLD); + wakeup((caddr_t)t); + PROCTREE_LOCK(PT_RELEASE); + return (0); + } + PROCTREE_LOCK(PT_RELEASE); } p->p_xstat = 0; ruadd(&q->p_stats->p_cru, p->p_ru); @@ -519,10 +519,14 @@ * Unlink it from its process group and free it. */ leavepgrp(p); + ALLPROC_LOCK(AP_EXCLUSIVE); LIST_REMOVE(p, p_list); /* off zombproc */ ALLPROC_LOCK(AP_RELEASE); + + PROCTREE_LOCK(PT_EXCLUSIVE); LIST_REMOVE(p, p_sibling); + PROCTREE_LOCK(PT_RELEASE); if (--p->p_procsig->ps_refcnt == 0) { if (p->p_sigacts != &p->p_addr->u_sigacts) @@ -545,6 +549,7 @@ if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); p->p_flag |= P_WAITED; q->p_retval[0] = p->p_pid; #ifdef COMPAT_43 @@ -563,6 +568,7 @@ } mtx_exit(&sched_lock, MTX_SPIN); } + PROCTREE_LOCK(PT_RELEASE); if (nfound == 0) return (ECHILD); if (uap->options & WNOHANG) { @@ -575,7 +581,8 @@ } /* - * make process 'parent' the new parent of process 'child'. + * Make process 'parent' the new parent of process 'child'. + * Must be called with an exclusive hold of proctree lock. */ void proc_reparent(child, parent) @@ -583,6 +590,7 @@ register struct proc *parent; { + PROCTREE_ASSERT(PT_EXCLUSIVE); if (child->p_pptr == parent) return; Index: kern/kern_fork.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_fork.c,v retrieving revision 1.90 diff -u -r1.90 kern_fork.c --- kern/kern_fork.c 2000/12/13 00:17:01 1.90 +++ kern/kern_fork.c 2000/12/17 18:58:08 @@ -476,8 +476,10 @@ pptr = initproc; else pptr = p1; + PROCTREE_LOCK(PT_EXCLUSIVE); p2->p_pptr = pptr; LIST_INSERT_HEAD(&pptr->p_children, p2, p_sibling); + PROCTREE_LOCK(PT_RELEASE); LIST_INIT(&p2->p_children); LIST_INIT(&p2->p_heldmtx); LIST_INIT(&p2->p_contested); Index: kern/kern_kthread.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_kthread.c,v retrieving revision 1.10 diff -u -r1.10 kern_kthread.c --- kern/kern_kthread.c 2000/12/15 20:08:18 1.10 +++ kern/kern_kthread.c 2000/12/18 04:48:34 @@ -30,6 +30,7 @@ #include <sys/systm.h> #include <sys/proc.h> #include <sys/kthread.h> +#include <sys/lock.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/unistd.h> @@ -113,7 +114,10 @@ void kthread_exit(int ecode) { + + PROCTREE_LOCK(PT_EXCLUSIVE); proc_reparent(curproc, initproc); + PROCTREE_LOCK(PT_RELEASE); exit1(curproc, W_EXITCODE(ecode, 0)); } Index: kern/kern_ktrace.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v retrieving revision 1.45 diff -u -r1.45 kern_ktrace.c --- kern/kern_ktrace.c 2000/12/13 00:17:01 1.45 +++ kern/kern_ktrace.c 2000/12/18 00:13:00 @@ -317,7 +317,6 @@ ret |= ktrsetchildren(curp, p, ops, facs, vp); else ret |= ktrops(curp, p, ops, facs, vp); - } else { /* * by pid @@ -426,6 +425,7 @@ register int ret = 0; p = top; + PROCTREE_LOCK(PT_SHARED); for (;;) { ret |= ktrops(curp, p, ops, facs, vp); /* @@ -436,8 +436,10 @@ if (!LIST_EMPTY(&p->p_children)) p = LIST_FIRST(&p->p_children); else for (;;) { - if (p == top) + if (p == top) { + PROCTREE_LOCK(PT_RELEASE); return (ret); + } if (LIST_NEXT(p, p_sibling)) { p = LIST_NEXT(p, p_sibling); break; Index: kern/kern_proc.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_proc.c,v retrieving revision 1.79 diff -u -r1.79 kern_proc.c --- kern/kern_proc.c 2000/12/13 00:17:01 1.79 +++ kern/kern_proc.c 2000/12/18 03:01:57 @@ -73,6 +73,7 @@ struct proclist allproc; struct proclist zombproc; struct lock allproc_lock; +struct lock proctree_lock; vm_zone_t proc_zone; vm_zone_t ithread_zone; @@ -84,6 +85,7 @@ { lockinit(&allproc_lock, PZERO, "allproc", 0, 0); + lockinit(&proctree_lock, PZERO, "proctree", 0, 0); LIST_INIT(&allproc); LIST_INIT(&zombproc); pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); @@ -106,11 +108,16 @@ inferior(p) register struct proc *p; { + int rval = 1; + PROCTREE_LOCK(PT_SHARED); for (; p != curproc; p = p->p_pptr) - if (p->p_pid == 0) - return (0); - return (1); + if (p->p_pid == 0) { + rval = 0; + break; + } + PROCTREE_LOCK(PT_RELEASE); + return (rval); } /* @@ -281,6 +288,7 @@ * Check p's parent to see whether p qualifies its own process * group; if so, adjust count for p's process group. */ + PROCTREE_LOCK(PT_SHARED); if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && hispgrp->pg_session == mysession) { if (entering) @@ -303,6 +311,7 @@ else if (--hispgrp->pg_jobc == 0) orphanpg(hispgrp); } + PROCTREE_LOCK(PT_RELEASE); } /* @@ -414,8 +423,10 @@ kp->ki_rtprio = p->p_rtprio; kp->ki_runtime = p->p_runtime; kp->ki_pid = p->p_pid; + PROCTREE_LOCK(PT_SHARED); if (p->p_pptr) kp->ki_ppid = p->p_pptr->p_pid; + PROCTREE_LOCK(PT_RELEASE); sp = NULL; if (p->p_pgrp) { kp->ki_pgid = p->p_pgrp->pg_id; Index: kern/kern_prot.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v retrieving revision 1.69 diff -u -r1.69 kern_prot.c --- kern/kern_prot.c 2000/11/30 19:09:48 1.69 +++ kern/kern_prot.c 2000/12/18 03:44:08 @@ -50,6 +50,7 @@ #include <sys/systm.h> #include <sys/sysproto.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/pioctl.h> @@ -64,9 +65,6 @@ }; #endif -/* - * NOT MP SAFE due to p_pptr access - */ /* ARGSUSED */ int getpid(p, uap) @@ -76,7 +74,9 @@ p->p_retval[0] = p->p_pid; #if defined(COMPAT_43) || defined(COMPAT_SUNOS) + PROCTREE_LOCK(PT_SHARED); p->p_retval[1] = p->p_pptr->p_pid; + PROCTREE_LOCK(PT_RELEASE); #endif return (0); } @@ -93,7 +93,9 @@ struct getppid_args *uap; { + PROCTREE_LOCK(PT_SHARED); p->p_retval[0] = p->p_pptr->p_pid; + PROCTREE_LOCK(PT_RELEASE); return (0); } Index: kern/kern_sig.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v retrieving revision 1.97 diff -u -r1.97 kern_sig.c --- kern/kern_sig.c 2000/12/16 21:03:48 1.97 +++ kern/kern_sig.c 2000/12/18 04:48:34 @@ -1158,9 +1158,11 @@ goto out; SIGDELSET(p->p_siglist, sig); p->p_xstat = sig; + PROCTREE_LOCK(PT_SHARED); if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); stop(p); + PROCTREE_LOCK(PT_RELEASE); goto out; } else goto runfast; @@ -1296,14 +1298,17 @@ * stopped until released by the parent. */ p->p_xstat = sig; + PROCTREE_LOCK(PT_SHARED); psignal(p->p_pptr, SIGCHLD); do { stop(p); + PROCTREE_LOCK(PT_RELEASE); mtx_enter(&sched_lock, MTX_SPIN); DROP_GIANT_NOSWITCH(); mi_switch(); mtx_exit(&sched_lock, MTX_SPIN); PICKUP_GIANT(); + PROCTREE_LOCK(PT_SHARED); } while (!trace_req(p) && p->p_flag & P_TRACED); @@ -1369,9 +1374,11 @@ prop & SA_TTYSTOP)) break; /* == ignore */ p->p_xstat = sig; + PROCTREE_LOCK(PT_SHARED); stop(p); if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); + PROCTREE_LOCK(PT_RELEASE); mtx_enter(&sched_lock, MTX_SPIN); DROP_GIANT_NOSWITCH(); mi_switch(); @@ -1414,13 +1421,15 @@ /* * Put the argument process into the stopped state and notify the parent * via wakeup. Signals are handled elsewhere. The process must not be - * on the run queue. + * on the run queue. Must be called with at least a shared hold of the + * proctree lock. */ void stop(p) register struct proc *p; { + PROCTREE_ASSERT(PT_SHARED); mtx_enter(&sched_lock, MTX_SPIN); p->p_stat = SSTOP; p->p_flag &= ~P_WAITED; Index: kern/sys_process.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_process.c,v retrieving revision 1.55 diff -u -r1.55 sys_process.c --- kern/sys_process.c 2000/12/12 07:25:53 1.55 +++ kern/sys_process.c 2000/12/18 01:24:58 @@ -276,8 +276,12 @@ return EPERM; /* not being traced by YOU */ - if (p->p_pptr != curp) + PROCTREE_LOCK(PT_SHARED); + if (p->p_pptr != curp) { + PROCTREE_LOCK(PT_RELEASE); return EBUSY; + } + PROCTREE_LOCK(PT_RELEASE); /* not currently stopped */ mtx_enter(&sched_lock, MTX_SPIN); @@ -311,15 +315,19 @@ case PT_TRACE_ME: /* set my trace flag and "owner" so it can read/write me */ p->p_flag |= P_TRACED; + PROCTREE_LOCK(PT_SHARED); p->p_oppid = p->p_pptr->p_pid; + PROCTREE_LOCK(PT_RELEASE); return 0; case PT_ATTACH: /* security check done above */ p->p_flag |= P_TRACED; + PROCTREE_LOCK(PT_EXCLUSIVE); p->p_oppid = p->p_pptr->p_pid; if (p->p_pptr != curp) proc_reparent(p, curp); + PROCTREE_LOCK(PT_RELEASE); uap->data = SIGSTOP; goto sendsig; /* in PT_CONTINUE below */ @@ -350,12 +358,14 @@ if (uap->req == PT_DETACH) { /* reset process parent */ + PROCTREE_LOCK(PT_EXCLUSIVE); if (p->p_oppid != p->p_pptr->p_pid) { struct proc *pp; pp = pfind(p->p_oppid); proc_reparent(p, pp ? pp : initproc); } + PROCTREE_LOCK(PT_RELEASE); p->p_flag &= ~(P_TRACED | P_WAITED); p->p_oppid = 0; Index: miscfs/procfs/procfs_ctl.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_ctl.c,v retrieving revision 1.22 diff -u -r1.22 procfs_ctl.c --- miscfs/procfs/procfs_ctl.c 2000/12/13 04:28:24 1.22 +++ miscfs/procfs/procfs_ctl.c 2000/12/19 20:57:43 @@ -144,10 +144,12 @@ p->p_flag |= P_TRACED; faultin(p); p->p_xstat = 0; /* XXX ? */ + PROCTREE_LOCK(PT_EXCLUSIVE); if (p->p_pptr != curp) { p->p_oppid = p->p_pptr->p_pid; proc_reparent(p, curp); } + PROCTREE_LOCK(PT_RELEASE); psignal(p, SIGSTOP); return (0); } @@ -164,12 +166,15 @@ break; default: + PROCTREE_LOCK(PT_SHARED); mtx_enter(&sched_lock, MTX_SPIN); if (!TRACE_WAIT_P(curp, p)) { mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); return (EBUSY); } mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); } @@ -204,6 +209,7 @@ SIGDELSET(p->p_siglist, SIGTRAP); /* give process back to original parent */ + PROCTREE_LOCK(PT_EXCLUSIVE); if (p->p_oppid != p->p_pptr->p_pid) { struct proc *pp; @@ -211,6 +217,7 @@ if (pp) proc_reparent(p, pp); } + PROCTREE_LOCK(PT_RELEASE); p->p_oppid = 0; p->p_flag &= ~P_WAITED; /* XXX ? */ @@ -244,19 +251,23 @@ case PROCFS_CTL_WAIT: error = 0; if (p->p_flag & P_TRACED) { + PROCTREE_LOCK(PT_SHARED); mtx_enter(&sched_lock, MTX_SPIN); while (error == 0 && (p->p_stat != SSTOP) && (p->p_flag & P_TRACED) && (p->p_pptr == curp)) { mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); error = tsleep((caddr_t) p, PWAIT|PCATCH, "procfsx", 0); + PROCTREE_LOCK(PT_SHARED); mtx_enter(&sched_lock, MTX_SPIN); } if (error == 0 && !TRACE_WAIT_P(curp, p)) error = EBUSY; mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); } else { mtx_enter(&sched_lock, MTX_SPIN); while (error == 0 && p->p_stat != SSTOP) { @@ -317,6 +328,7 @@ } else { nm = vfs_findname(signames, msg, xlen); if (nm) { + PROCTREE_LOCK(PT_SHARED); mtx_enter(&sched_lock, MTX_SPIN); if (TRACE_WAIT_P(curp, p)) { p->p_xstat = nm->nm_val; @@ -325,8 +337,10 @@ #endif setrunnable(p); mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); } else { mtx_exit(&sched_lock, MTX_SPIN); + PROCTREE_LOCK(PT_RELEASE); psignal(p, nm->nm_val); } error = 0; Index: miscfs/procfs/procfs_status.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_status.c,v retrieving revision 1.23 diff -u -r1.23 procfs_status.c --- miscfs/procfs/procfs_status.c 2000/11/08 21:53:05 1.23 +++ miscfs/procfs/procfs_status.c 2000/12/18 01:30:10 @@ -78,7 +78,9 @@ return (EOPNOTSUPP); pid = p->p_pid; + PROCTREE_LOCK(PT_SHARED); ppid = p->p_pptr ? p->p_pptr->p_pid : 0; + PROCTREE_LOCK(PT_RELEASE); pgid = p->p_pgrp->pg_id; sess = p->p_pgrp->pg_session; sid = sess->s_leader ? sess->s_leader->p_pid : 0; Index: sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.136 diff -u -r1.136 proc.h --- sys/proc.h 2000/12/15 00:10:32 1.136 +++ sys/proc.h 2000/12/18 05:46:41 @@ -415,6 +415,17 @@ #define AP_EXCLUSIVE LK_EXCLUSIVE #define AP_RELEASE LK_RELEASE +/* Lock and unlock the proc child and sibling lists. */ +#define PROCTREE_LOCK(how) \ + lockmgr(&proctree_lock, (how), NULL, CURPROC) + +#define PROCTREE_ASSERT(what) \ + LOCKMGR_ASSERT(&proctree_lock, (what), CURPROC) + +#define PT_SHARED LK_SHARED +#define PT_EXCLUSIVE LK_EXCLUSIVE +#define PT_RELEASE LK_RELEASE + /* Hold process U-area in memory, normally for ptrace/procfs work. */ #define PHOLD(p) do { \ PROC_LOCK(p); \ @@ -439,6 +450,7 @@ extern u_long pgrphash; extern struct lock allproc_lock; +extern struct lock proctree_lock; extern struct proc proc0; /* Process slot for swapper. */ extern int hogticks; /* Limit on kernel cpu hogs. */ extern int nprocs, maxproc; /* Current and max number of procs. */ --==_Exmh_19954384880-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-smp" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001220212106.41C6CBA7D>