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