Module Name:    src
Committed By:   rmind
Date:           Sat Apr 25 15:06:33 UTC 2009

Modified Files:
        src/sys/kern: kern_exit.c kern_proc.c kern_prot.c subr_prf.c tty.c
        src/sys/miscfs/specfs: spec_vnops.c
        src/sys/sys: proc.h

Log Message:
- Rearrange pg_delete() and pg_remove() (renamed pg_free), thus
  proc_enterpgrp() with proc_leavepgrp() to free process group and/or
  session without proc_lock held.
- Rename SESSHOLD() and SESSRELE() to  to proc_sesshold() and
  proc_sessrele().  The later releases proc_lock now.

Quick OK by <ad>.


To generate a diff of this commit:
cvs rdiff -u -r1.219 -r1.220 src/sys/kern/kern_exit.c
cvs rdiff -u -r1.150 -r1.151 src/sys/kern/kern_proc.c
cvs rdiff -u -r1.108 -r1.109 src/sys/kern/kern_prot.c
cvs rdiff -u -r1.132 -r1.133 src/sys/kern/subr_prf.c
cvs rdiff -u -r1.230 -r1.231 src/sys/kern/tty.c
cvs rdiff -u -r1.123 -r1.124 src/sys/miscfs/specfs/spec_vnops.c
cvs rdiff -u -r1.287 -r1.288 src/sys/sys/proc.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_exit.c
diff -u src/sys/kern/kern_exit.c:1.219 src/sys/kern/kern_exit.c:1.220
--- src/sys/kern/kern_exit.c:1.219	Sat Mar 28 21:38:55 2009
+++ src/sys/kern/kern_exit.c	Sat Apr 25 15:06:31 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_exit.c,v 1.219 2009/03/28 21:38:55 rmind Exp $	*/
+/*	$NetBSD: kern_exit.c,v 1.220 2009/04/25 15:06:31 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.219 2009/03/28 21:38:55 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.220 2009/04/25 15:06:31 rmind Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_perfctrs.h"
@@ -378,8 +378,8 @@
 
 		if (vprevoke != NULL || vprele != NULL) {
 			if (vprevoke != NULL) {
-				SESSRELE(sp);
-				mutex_exit(proc_lock);
+				/* Releases proc_lock. */
+				proc_sessrele(sp);
 				VOP_REVOKE(vprevoke, REVOKEALL);
 			} else
 				mutex_exit(proc_lock);
@@ -890,12 +890,6 @@
 		return;
 	}
 
-	/*
-	 * Finally finished with old proc entry.  Unlink it from its process
-	 * group.
-	 */
-	leavepgrp(p);
-
 	sched_proc_exit(parent, p);
 
 	/*
@@ -933,7 +927,12 @@
 	 * Let pid be reallocated.
 	 */
 	proc_free_pid(p);
-	mutex_exit(proc_lock);
+
+	/*
+	 * Unlink process from its process group.
+	 * Releases the proc_lock.
+	 */
+	proc_leavepgrp(p);
 
 	/*
 	 * Delay release until after lwp_free.

Index: src/sys/kern/kern_proc.c
diff -u src/sys/kern/kern_proc.c:1.150 src/sys/kern/kern_proc.c:1.151
--- src/sys/kern/kern_proc.c:1.150	Thu Apr 16 14:56:41 2009
+++ src/sys/kern/kern_proc.c	Sat Apr 25 15:06:31 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_proc.c,v 1.150 2009/04/16 14:56:41 rmind Exp $	*/
+/*	$NetBSD: kern_proc.c,v 1.151 2009/04/25 15:06:31 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.150 2009/04/16 14:56:41 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.151 2009/04/25 15:06:31 rmind Exp $");
 
 #include "opt_kstack.h"
 #include "opt_maxuprc.h"
@@ -226,8 +226,9 @@
 	{ NULL		},
 };
 
-static void orphanpg(struct pgrp *);
-static void pg_delete(pid_t);
+static struct pgrp *	pg_remove(pid_t);
+static void		pg_delete(pid_t);
+static void		orphanpg(struct pgrp *);
 
 static specificdata_domain_t proc_specificdata_domain;
 
@@ -376,6 +377,41 @@
 }
 
 /*
+ * Session reference counting.
+ */
+
+void
+proc_sesshold(struct session *ss)
+{
+
+	KASSERT(mutex_owned(proc_lock));
+	ss->s_count++;
+}
+
+void
+proc_sessrele(struct session *ss)
+{
+
+	KASSERT(mutex_owned(proc_lock));
+	/*
+	 * We keep the pgrp with the same id as the session in order to
+	 * stop a process being given the same pid.  Since the pgrp holds
+	 * a reference to the session, it must be a 'zombie' pgrp by now.
+	 */
+	if (--ss->s_count == 0) {
+		struct pgrp *pg;
+
+		pg = pg_remove(ss->s_sid);
+		mutex_exit(proc_lock);
+
+		kmem_free(pg, sizeof(struct pgrp));
+		kmem_free(ss, sizeof(struct session));
+	} else {
+		mutex_exit(proc_lock);
+	}
+}
+
+/*
  * Check that the specified process group is in the session of the
  * specified process.
  * Treats -ve ids as process ids.
@@ -649,7 +685,7 @@
 }
 
 /*
- * Move p to a new or existing process group (and session)
+ * proc_enterpgrp: move p to a new or existing process group (and session).
  *
  * If we are creating a new pgrp, the pgid should equal
  * the calling process' pid.
@@ -660,7 +696,7 @@
  * Only called from sys_setsid and sys_setpgid.
  */
 int
-enterpgrp(struct proc *curp, pid_t pid, pid_t pgid, int mksess)
+proc_enterpgrp(struct proc *curp, pid_t pid, pid_t pgid, bool mksess)
 {
 	struct pgrp *new_pgrp, *pgrp;
 	struct session *sess;
@@ -668,10 +704,7 @@
 	int rval;
 	pid_t pg_id = NO_PGID;
 
-	if (mksess)
-		sess = kmem_alloc(sizeof(*sess), KM_SLEEP);
-	else
-		sess = NULL;
+	sess = mksess ? kmem_alloc(sizeof(*sess), KM_SLEEP) : NULL;
 
 	/* Allocate data areas we might need before doing any validity checks */
 	mutex_enter(proc_lock);		/* Because pid_table might change */
@@ -764,7 +797,7 @@
 			p->p_lflag &= ~PL_CONTROLT;
 		} else {
 			sess = p->p_pgrp->pg_session;
-			SESSHOLD(sess);
+			proc_sesshold(sess);
 		}
 		pgrp->pg_session = sess;
 		sess = NULL;
@@ -804,9 +837,12 @@
 	mutex_spin_exit(&tty_lock);
 
     done:
-	if (pg_id != NO_PGID)
+	if (pg_id != NO_PGID) {
+		/* Releases proc_lock. */
 		pg_delete(pg_id);
-	mutex_exit(proc_lock);
+	} else {
+		mutex_exit(proc_lock);
+	}
 	if (sess != NULL)
 		kmem_free(sess, sizeof(*sess));
 	if (new_pgrp != NULL)
@@ -820,11 +856,11 @@
 }
 
 /*
- * Remove a process from its process group.  Must be called with the
- * proc_lock held.
+ * proc_leavepgrp: remove a process from its process group.
+ *  => must be called with the proc_lock held, which will be released;
  */
 void
-leavepgrp(struct proc *p)
+proc_leavepgrp(struct proc *p)
 {
 	struct pgrp *pgrp;
 
@@ -837,15 +873,21 @@
 	p->p_pgrp = NULL;
 	mutex_spin_exit(&tty_lock);
 
-	if (LIST_EMPTY(&pgrp->pg_members))
+	if (LIST_EMPTY(&pgrp->pg_members)) {
+		/* Releases proc_lock. */
 		pg_delete(pgrp->pg_id);
+	} else {
+		mutex_exit(proc_lock);
+	}
 }
 
 /*
- * Free a process group.  Must be called with the proc_lock held.
+ * pg_remove: remove a process group from the table.
+ *  => must be called with the proc_lock held;
+ *  => returns process group to free;
  */
-static void
-pg_free(pid_t pg_id)
+static struct pgrp *
+pg_remove(pid_t pg_id)
 {
 	struct pgrp *pgrp;
 	struct pid_table *pt;
@@ -854,91 +896,66 @@
 
 	pt = &pid_table[pg_id & pid_tbl_mask];
 	pgrp = pt->pt_pgrp;
-#ifdef DIAGNOSTIC
-	if (__predict_false(!pgrp || pgrp->pg_id != pg_id
-	    || !LIST_EMPTY(&pgrp->pg_members)))
-		panic("pg_free: process group absent or has members");
-#endif
-	pt->pt_pgrp = 0;
+
+	KASSERT(pgrp != NULL);
+	KASSERT(pgrp->pg_id == pg_id);
+	KASSERT(LIST_EMPTY(&pgrp->pg_members));
+
+	pt->pt_pgrp = NULL;
 
 	if (!P_VALID(pt->pt_proc)) {
-		/* orphaned pgrp, put slot onto free list */
-#ifdef DIAGNOSTIC
-		if (__predict_false(P_NEXT(pt->pt_proc) & pid_tbl_mask))
-			panic("pg_free: process slot on free list");
-#endif
+		/* Orphaned pgrp, put slot onto free list. */
+		KASSERT((P_NEXT(pt->pt_proc) & pid_tbl_mask) == 0);
 		pg_id &= pid_tbl_mask;
 		pt = &pid_table[last_free_pt];
 		pt->pt_proc = P_FREE(P_NEXT(pt->pt_proc) | pg_id);
 		last_free_pt = pg_id;
 		pid_alloc_cnt--;
 	}
-	kmem_free(pgrp, sizeof(*pgrp));
+	return pgrp;
 }
 
 /*
- * Delete a process group.  Must be called with the proc_lock held.
+ * pg_delete: delete and free a process group.
+ *  => must be called with the proc_lock held, which will be released.
  */
 static void
 pg_delete(pid_t pg_id)
 {
-	struct pgrp *pgrp;
+	struct pgrp *pg;
 	struct tty *ttyp;
 	struct session *ss;
-	int is_pgrp_leader;
 
 	KASSERT(mutex_owned(proc_lock));
 
-	pgrp = pid_table[pg_id & pid_tbl_mask].pt_pgrp;
-	if (pgrp == NULL || pgrp->pg_id != pg_id ||
-	    !LIST_EMPTY(&pgrp->pg_members))
+	pg = pid_table[pg_id & pid_tbl_mask].pt_pgrp;
+	if (pg == NULL || pg->pg_id != pg_id || !LIST_EMPTY(&pg->pg_members)) {
+		mutex_exit(proc_lock);
 		return;
+	}
 
-	ss = pgrp->pg_session;
+	ss = pg->pg_session;
 
 	/* Remove reference (if any) from tty to this process group */
 	mutex_spin_enter(&tty_lock);
 	ttyp = ss->s_ttyp;
-	if (ttyp != NULL && ttyp->t_pgrp == pgrp) {
+	if (ttyp != NULL && ttyp->t_pgrp == pg) {
 		ttyp->t_pgrp = NULL;
-#ifdef DIAGNOSTIC
-		if (ttyp->t_session != ss)
-			panic("pg_delete: wrong session on terminal");
-#endif
+		KASSERT(ttyp->t_session == ss);
 	}
 	mutex_spin_exit(&tty_lock);
 
 	/*
-	 * The leading process group in a session is freed
-	 * by sessdelete() if last reference.
+	 * The leading process group in a session is freed by proc_sessrele(),
+	 * if last reference.  Note: proc_sessrele() releases proc_lock.
 	 */
-	is_pgrp_leader = (ss->s_sid == pgrp->pg_id);
-	SESSRELE(ss);
+	pg = (ss->s_sid != pg->pg_id) ? pg_remove(pg_id) : NULL;
+	proc_sessrele(ss);
 
-	if (is_pgrp_leader)
-		return;
-
-	pg_free(pg_id);
-}
-
-/*
- * Delete session - called from SESSRELE when s_count becomes zero.
- * Must be called with the proc_lock held.
- */
-void
-sessdelete(struct session *ss)
-{
-
-	KASSERT(mutex_owned(proc_lock));
-
-	/*
-	 * We keep the pgrp with the same id as the session in
-	 * order to stop a process being given the same pid.
-	 * Since the pgrp holds a reference to the session, it
-	 * must be a 'zombie' pgrp by now.
-	 */
-	pg_free(ss->s_sid);
-	kmem_free(ss, sizeof(*ss));
+	if (pg != NULL) {
+		/* Free it, if was not done by proc_sessrele(). */
+		kmem_free(pg, sizeof(struct pgrp));
+	}
 }
 
 /*

Index: src/sys/kern/kern_prot.c
diff -u src/sys/kern/kern_prot.c:1.108 src/sys/kern/kern_prot.c:1.109
--- src/sys/kern/kern_prot.c:1.108	Sat Oct 11 13:40:57 2008
+++ src/sys/kern/kern_prot.c	Sat Apr 25 15:06:31 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_prot.c,v 1.108 2008/10/11 13:40:57 pooka Exp $	*/
+/*	$NetBSD: kern_prot.c,v 1.109 2009/04/25 15:06:31 rmind Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.108 2008/10/11 13:40:57 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.109 2009/04/25 15:06:31 rmind Exp $");
 
 #include "opt_compat_43.h"
 
@@ -238,14 +238,13 @@
 	    UIO_USERSPACE);
 }
 
-/* ARGSUSED */
 int
 sys_setsid(struct lwp *l, const void *v, register_t *retval)
 {
 	struct proc *p = l->l_proc;
 	int error;
 
-	error = enterpgrp(p, p->p_pid, p->p_pid, 1);
+	error = proc_enterpgrp(p, p->p_pid, p->p_pid, true);
 	*retval = p->p_pid;
 	return (error);
 }
@@ -265,11 +264,11 @@
  * 	there must exist some pid in same session having pgid (EPERM)
  * pid must not be session leader (EPERM)
  *
- * Permission checks now in enterpgrp()
+ * Permission checks now in proc_enterpgrp()
  */
-/* ARGSUSED */
 int
-sys_setpgid(struct lwp *l, const struct sys_setpgid_args *uap, register_t *retval)
+sys_setpgid(struct lwp *l, const struct sys_setpgid_args *uap,
+    register_t *retval)
 {
 	/* {
 		syscallarg(int) pid;
@@ -285,7 +284,7 @@
 	if ((pgid = SCARG(uap, pgid)) == 0)
 		pgid = targp;
 
-	return enterpgrp(p, targp, pgid, 0);
+	return proc_enterpgrp(p, targp, pgid, false);
 }
 
 /*

Index: src/sys/kern/subr_prf.c
diff -u src/sys/kern/subr_prf.c:1.132 src/sys/kern/subr_prf.c:1.133
--- src/sys/kern/subr_prf.c:1.132	Sun Mar 15 17:14:40 2009
+++ src/sys/kern/subr_prf.c	Sat Apr 25 15:06:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_prf.c,v 1.132 2009/03/15 17:14:40 cegger Exp $	*/
+/*	$NetBSD: subr_prf.c,v 1.133 2009/04/25 15:06:32 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1986, 1988, 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.132 2009/03/15 17:14:40 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.133 2009/04/25 15:06:32 rmind Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipkdb.h"
@@ -512,7 +512,7 @@
 
 	mutex_enter(proc_lock);
 	if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) {
-		SESSHOLD(p->p_session);
+		proc_sesshold(p->p_session);
 		cookie = (tpr_t)p->p_session;
 	}
 	mutex_exit(proc_lock);
@@ -530,8 +530,8 @@
 
 	if (sess) {
 		mutex_enter(proc_lock);
-		SESSRELE((struct session *) sess);
-		mutex_exit(proc_lock);
+		/* Releases proc_lock. */
+		proc_sessrele((struct session *)sess);
 	}
 }
 

Index: src/sys/kern/tty.c
diff -u src/sys/kern/tty.c:1.230 src/sys/kern/tty.c:1.231
--- src/sys/kern/tty.c:1.230	Thu Jan 22 20:40:20 2009
+++ src/sys/kern/tty.c	Sat Apr 25 15:06:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty.c,v 1.230 2009/01/22 20:40:20 drochner Exp $	*/
+/*	$NetBSD: tty.c,v 1.231 2009/04/25 15:06:32 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.230 2009/01/22 20:40:20 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.231 2009/04/25 15:06:32 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -344,11 +344,11 @@
 
 	mutex_spin_exit(&tty_lock);
 
-	mutex_enter(proc_lock);
-	if (sess != NULL)
-		SESSRELE(sess);
-	mutex_exit(proc_lock);
-
+	if (sess != NULL) {
+		mutex_enter(proc_lock);
+		/* Releases proc_lock. */
+		proc_sessrele(sess);
+	}
 	return (0);
 }
 
@@ -1164,9 +1164,9 @@
 		 * it must equal `p_session', in which case the session
 		 * already has the correct reference count.
 		 */
-		if (tp->t_session == NULL)
-			SESSHOLD(p->p_session);
-
+		if (tp->t_session == NULL) {
+			proc_sesshold(p->p_session);
+		}
 		tp->t_session = p->p_session;
 		tp->t_pgrp = p->p_pgrp;
 		p->p_session->s_ttyp = tp;

Index: src/sys/miscfs/specfs/spec_vnops.c
diff -u src/sys/miscfs/specfs/spec_vnops.c:1.123 src/sys/miscfs/specfs/spec_vnops.c:1.124
--- src/sys/miscfs/specfs/spec_vnops.c:1.123	Sun Feb 22 20:28:06 2009
+++ src/sys/miscfs/specfs/spec_vnops.c	Sat Apr 25 15:06:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: spec_vnops.c,v 1.123 2009/02/22 20:28:06 ad Exp $	*/
+/*	$NetBSD: spec_vnops.c,v 1.124 2009/04/25 15:06:32 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.123 2009/02/22 20:28:06 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.124 2009/04/25 15:06:32 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -940,8 +940,8 @@
 				sess->s_ttyp->t_pgrp = NULL;
 				sess->s_ttyp->t_session = NULL;
 				mutex_spin_exit(&tty_lock);
-				SESSRELE(sess);
-				mutex_exit(proc_lock);
+				/* Releases proc_lock. */
+				proc_sessrele(sess);
 			} else {
 				mutex_spin_exit(&tty_lock);
 				if (sess->s_ttyp->t_pgrp != NULL)

Index: src/sys/sys/proc.h
diff -u src/sys/sys/proc.h:1.287 src/sys/sys/proc.h:1.288
--- src/sys/sys/proc.h:1.287	Sun Apr 19 22:15:39 2009
+++ src/sys/sys/proc.h	Sat Apr 25 15:06:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: proc.h,v 1.287 2009/04/19 22:15:39 rmind Exp $	*/
+/*	$NetBSD: proc.h,v 1.288 2009/04/25 15:06:32 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -428,13 +428,6 @@
 #define	NO_PGID		((pid_t)-1)
 
 #define	SESS_LEADER(p)	((p)->p_session->s_leader == (p))
-#define	SESSHOLD(s)	((s)->s_count++)
-#define	SESSRELE(s)							\
-do {									\
-	if (--(s)->s_count == 0)					\
-		sessdelete(s);						\
-} while (/* CONSTCOND */ 0)
-
 
 /*
  * Flags passed to fork1().
@@ -477,11 +470,13 @@
 #define pgfind(pgid) pg_find((pgid), PFIND_UNLOCK)
 
 struct simplelock;
-int	enterpgrp(struct proc *, pid_t, pid_t, int);
-void	leavepgrp(struct proc *);
-void	fixjobc(struct proc *, struct pgrp *, int);
-void	sessdelete(struct session *);
+
 void	procinit(void);
+int	proc_enterpgrp(struct proc *, pid_t, pid_t, bool);
+void	proc_leavepgrp(struct proc *);
+void	proc_sesshold(struct session *);
+void	proc_sessrele(struct session *);
+void	fixjobc(struct proc *, struct pgrp *, int);
 
 int	ltsleep(wchan_t, pri_t, const char *, int, volatile struct simplelock *);
 int	mtsleep(wchan_t, pri_t, const char *, int, kmutex_t *);

Reply via email to