diff options
author | tanimura <tanimura@FreeBSD.org> | 2002-02-23 11:12:57 +0000 |
---|---|---|
committer | tanimura <tanimura@FreeBSD.org> | 2002-02-23 11:12:57 +0000 |
commit | a09da298590e8c11ebafa37f79e0046814665237 (patch) | |
tree | 2289c653c0f7aa23498f82b603c33107952652ec /sys/kern/kern_descrip.c | |
parent | 33e8ee5265ca2838260ab581a9cebdedb1e1e29b (diff) | |
download | FreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.zip FreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.tar.gz |
Lock struct pgrp, session and sigio.
New locks are:
- pgrpsess_lock which locks the whole pgrps and sessions,
- pg_mtx which protects the pgrp members, and
- s_mtx which protects the session members.
Please refer to sys/proc.h for the coverage of these locks.
Changes on the pgrp/session interface:
- pgfind() needs the pgrpsess_lock held.
- The caller of enterpgrp() is responsible to allocate a new pgrp and
session.
- Call enterthispgrp() in order to enter an existing pgrp.
- pgsignal() requires a pgrp lock held.
Reviewed by: jhb, alfred
Tested on: cvsup.jp.FreeBSD.org
(which is a quad-CPU machine running -current)
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 109 |
1 files changed, 91 insertions, 18 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index ea7fa2d..8e4726e 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -535,15 +535,22 @@ funsetown(sigio) if (sigio == NULL) return; + s = splhigh(); *(sigio->sio_myref) = NULL; splx(s); - if (sigio->sio_pgid < 0) { + if ((sigio)->sio_pgid < 0) { + struct pgrp *pg = (sigio)->sio_pgrp; + PGRP_LOCK(pg); SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio, sigio, sio_pgsigio); - } else /* if ((*sigiop)->sio_pgid > 0) */ { + PGRP_UNLOCK(pg); + } else { + struct proc *p = (sigio)->sio_proc; + PROC_LOCK(p); SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio, sigio, sio_pgsigio); + PROC_UNLOCK(p); } crfree(sigio->sio_ucred); FREE(sigio, M_SIGIO); @@ -554,10 +561,52 @@ void funsetownlst(sigiolst) struct sigiolst *sigiolst; { + int s; struct sigio *sigio; + struct proc *p; + struct pgrp *pg; + + sigio = SLIST_FIRST(sigiolst); + if (sigio == NULL) + return; + + p = NULL; + pg = NULL; + + /* + * Every entry of the list should belong + * to a single proc or pgrp. + */ + if (sigio->sio_pgid < 0) { + pg = sigio->sio_pgrp; + PGRP_LOCK_ASSERT(pg, MA_OWNED); + } else /* if (sigio->sio_pgid > 0) */ { + p = sigio->sio_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + } - while ((sigio = SLIST_FIRST(sigiolst)) != NULL) - funsetown(sigio); + while ((sigio = SLIST_FIRST(sigiolst)) != NULL) { + s = splhigh(); + *(sigio->sio_myref) = NULL; + splx(s); + if (pg != NULL) { + KASSERT(sigio->sio_pgid < 0, ("Proc sigio in pgrp sigio list")); + KASSERT(sigio->sio_pgrp == pg, ("Bogus pgrp in sigio list")); + SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio, sio_pgsigio); + PGRP_UNLOCK(pg); + crfree(sigio->sio_ucred); + FREE(sigio, M_SIGIO); + PGRP_LOCK(pg); + } else /* if (p != NULL) */ { + KASSERT(sigio->sio_pgid > 0, ("Pgrp sigio in proc sigio list")); + KASSERT(sigio->sio_proc == p, ("Bogus proc in sigio list")); + SLIST_REMOVE(&p->p_sigiolst, sigio, sigio, sio_pgsigio); + PROC_UNLOCK(p); + crfree(sigio->sio_ucred); + FREE(sigio, M_SIGIO); + PROC_LOCK(p); + } + } } /* @@ -574,16 +623,28 @@ fsetown(pgid, sigiop) struct proc *proc; struct pgrp *pgrp; struct sigio *sigio; - int s; + int s, ret; if (pgid == 0) { funsetown(*sigiop); return (0); } + + ret = 0; + + /* Allocate and fill in the new sigio out of locks. */ + MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK); + sigio->sio_pgid = pgid; + sigio->sio_ucred = crhold(curthread->td_proc->p_ucred); + sigio->sio_myref = sigiop; + + PGRPSESS_SLOCK(); if (pgid > 0) { proc = pfind(pgid); - if (proc == NULL) - return (ESRCH); + if (proc == NULL) { + ret = ESRCH; + goto fail; + } /* * Policy - Don't allow a process to FSETOWN a process @@ -593,17 +654,20 @@ fsetown(pgid, sigiop) * restrict FSETOWN to the current process or process * group for maximum safety. */ + PROC_UNLOCK(proc); if (proc->p_session != curthread->td_proc->p_session) { - PROC_UNLOCK(proc); - return (EPERM); + ret = EPERM; + goto fail; } - PROC_UNLOCK(proc); pgrp = NULL; } else /* if (pgid < 0) */ { pgrp = pgfind(-pgid); - if (pgrp == NULL) - return (ESRCH); + if (pgrp == NULL) { + ret = ESRCH; + goto fail; + } + PGRP_UNLOCK(pgrp); /* * Policy - Don't allow a process to FSETOWN a process @@ -613,27 +677,36 @@ fsetown(pgid, sigiop) * restrict FSETOWN to the current process or process * group for maximum safety. */ - if (pgrp->pg_session != curthread->td_proc->p_session) - return (EPERM); + if (pgrp->pg_session != curthread->td_proc->p_session) { + ret = EPERM; + goto fail; + } proc = NULL; } funsetown(*sigiop); - MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK); if (pgid > 0) { + PROC_LOCK(proc); SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio); sigio->sio_proc = proc; + PROC_UNLOCK(proc); } else { + PGRP_LOCK(pgrp); SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio); sigio->sio_pgrp = pgrp; + PGRP_UNLOCK(pgrp); } - sigio->sio_pgid = pgid; - sigio->sio_ucred = crhold(curthread->td_proc->p_ucred); - sigio->sio_myref = sigiop; + PGRPSESS_SUNLOCK(); s = splhigh(); *sigiop = sigio; splx(s); return (0); + +fail: + PGRPSESS_SUNLOCK(); + crfree(sigio->sio_ucred); + FREE(sigio, M_SIGIO); + return (ret); } /* |