Skip site navigation (1)Skip section navigation (2)
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>