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 *);