Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add a read/write lock to the proclists and PID hash tabl...
details: https://anonhg.NetBSD.org/src/rev/cdbfa7b2b923
branches: trunk
changeset: 474848:cdbfa7b2b923
user: thorpej <thorpej%NetBSD.org@localhost>
date: Thu Jul 22 21:08:30 1999 +0000
description:
Add a read/write lock to the proclists and PID hash table. Use the
write lock when doing PID allocation, and during the process exit path.
Use a read lock every where else, including within schedcpu() (interrupt
context). Note that holding the write lock implies blocking schedcpu()
from running (blocks softclock).
PID allocation is now MP-safe.
Note this actually fixes a bug on single processor systems that was probably
extremely difficult to tickle; it was possible that schedcpu() would run
off a bad pointer if the right clock interrupt happened to come in the
middle of a LIST_INSERT_HEAD() or LIST_REMOVE() to/from allproc.
diffstat:
sys/compat/svr4/svr4_misc.c | 19 +++--
sys/kern/init_main.c | 5 +-
sys/kern/kern_exit.c | 10 ++-
sys/kern/kern_fork.c | 8 +-
sys/kern/kern_ktrace.c | 8 ++-
sys/kern/kern_proc.c | 145 ++++++++++++++++++++++++++++++++++++++++++-
sys/kern/kern_resource.c | 6 +-
sys/kern/kern_sig.c | 8 +-
sys/kern/kern_synch.c | 4 +-
sys/kern/kern_sysctl.c | 5 +-
sys/sys/proc.h | 10 ++-
11 files changed, 203 insertions(+), 25 deletions(-)
diffs (truncated from 544 to 300 lines):
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/compat/svr4/svr4_misc.c
--- a/sys/compat/svr4/svr4_misc.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/compat/svr4/svr4_misc.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: svr4_misc.c,v 1.78 1999/07/20 21:54:06 thorpej Exp $ */
+/* $NetBSD: svr4_misc.c,v 1.79 1999/07/22 21:08:30 thorpej Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@@ -891,18 +891,22 @@
svr4_pfind(pid)
pid_t pid;
{
- struct proc *p;
+ struct proc *p = NULL;
+
+ proclist_lock_read(0);
/* look in the live processes */
if ((p = pfind(pid)) != NULL)
- return p;
+ goto out;
/* look in the zombies */
for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next)
if (p->p_pid == pid)
- return p;
+ goto out;
- return NULL;
+ out:
+ proclist_unlock_read();
+ return p;
}
@@ -1117,8 +1121,7 @@
register_t *retval;
{
struct svr4_sys_waitsys_args *uap = v;
- int nfound;
- int error;
+ int nfound, error, s;
struct proc *q, *t;
@@ -1195,7 +1198,9 @@
*/
leavepgrp(q);
+ s = proclist_lock_write();
LIST_REMOVE(q, p_list); /* off zombproc */
+ proclist_unlock_write(s);
LIST_REMOVE(q, p_sibling);
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/kern/init_main.c
--- a/sys/kern/init_main.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/kern/init_main.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: init_main.c,v 1.153 1999/07/06 21:44:10 thorpej Exp $ */
+/* $NetBSD: init_main.c,v 1.154 1999/07/22 21:08:31 thorpej Exp $ */
/*
* Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
@@ -225,7 +225,10 @@
/*
* Create process 0 (the swapper).
*/
+ s = proclist_lock_write();
LIST_INSERT_HEAD(&allproc, p, p_list);
+ proclist_unlock_write(s);
+
p->p_pgrp = &pgrp0;
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
LIST_INIT(&pgrp0.pg_members);
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/kern/kern_exit.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exit.c,v 1.72 1999/07/22 18:13:37 thorpej Exp $ */
+/* $NetBSD: kern_exit.c,v 1.73 1999/07/22 21:08:31 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -152,10 +152,12 @@
{
register struct proc *q, *nq;
register struct vmspace *vm;
+ int s;
if (p == initproc)
panic("init died (signal %d, exit %d)",
WTERMSIG(rv), WEXITSTATUS(rv));
+
#ifdef PGINPROF
vmsizmon();
#endif
@@ -257,9 +259,11 @@
* deadproc list later (using the p_hash member), and
* wake up the reaper when we do.
*/
+ s = proclist_lock_write();
LIST_REMOVE(p, p_hash);
LIST_REMOVE(p, p_list);
LIST_INSERT_HEAD(&zombproc, p, p_list);
+ proclist_unlock_write(s);
/*
* Give orphaned children to init(8).
@@ -424,7 +428,7 @@
} */ *uap = v;
register int nfound;
register struct proc *p, *t;
- int status, error;
+ int status, error, s;
if (SCARG(uap, pid) == 0)
SCARG(uap, pid) = -q->p_pgid;
@@ -494,7 +498,9 @@
*/
leavepgrp(p);
+ s = proclist_lock_write();
LIST_REMOVE(p, p_list); /* off zombproc */
+ proclist_unlock_write(s);
LIST_REMOVE(p, p_sibling);
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/kern/kern_fork.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_fork.c,v 1.60 1999/07/22 18:28:30 thorpej Exp $ */
+/* $NetBSD: kern_fork.c,v 1.61 1999/07/22 21:08:31 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -172,8 +172,9 @@
newproc = pool_get(&proc_pool, PR_WAITOK);
/*
- * BEGIN PID ALLOCATION. (Lock PID allocation variables eventually).
+ * BEGIN PID ALLOCATION.
*/
+ s = proclist_lock_write();
/*
* Find an unused process ID. We remember a range of unused IDs
@@ -253,8 +254,9 @@
LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
/*
- * END PID ALLOCATION. (Unlock PID allocation variables).
+ * END PID ALLOCATION.
*/
+ proclist_unlock_write(s);
/*
* Make a proc table entry for the new process.
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/kern/kern_ktrace.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_ktrace.c,v 1.35 1999/05/05 20:01:08 thorpej Exp $ */
+/* $NetBSD: kern_ktrace.c,v 1.36 1999/07/22 21:08:31 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -335,6 +335,7 @@
* Clear all uses of the tracefile
*/
if (KTROP(ops) == KTROP_CLEARFILE) {
+ proclist_lock_read(0);
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
if (p->p_tracep == fp) {
if (ktrcanset(curp, p))
@@ -343,6 +344,7 @@
error = EPERM;
}
}
+ proclist_unlock_read();
goto done;
}
/*
@@ -440,11 +442,13 @@
* Clear all uses of the tracefile
*/
if (KTROP(ops) == KTROP_CLEARFILE) {
+ proclist_lock_read(0);
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
if (p->p_tracep == vp &&
!ktrops(curp, p, KTROP_CLEAR, ~0, vp))
error = EPERM;
}
+ proclist_unlock_read();
goto done;
}
/*
@@ -617,10 +621,12 @@
*/
log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
error);
+ proclist_lock_read(0);
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
if (p->p_tracep == v)
ktrderef(p);
}
+ proclist_unlock_read();
}
/*
diff -r 6e6bd33da470 -r cdbfa7b2b923 sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c Thu Jul 22 20:58:18 1999 +0000
+++ b/sys/kern/kern_proc.c Thu Jul 22 21:08:30 1999 +0000
@@ -1,4 +1,41 @@
-/* $NetBSD: kern_proc.c,v 1.32 1999/07/22 18:13:37 thorpej Exp $ */
+/* $NetBSD: kern_proc.c,v 1.33 1999/07/22 21:08:31 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -78,6 +115,22 @@
struct proclist zombproc; /* resources have been freed */
/*
+ * Process list locking:
+ *
+ * We have two types of locks on the proclists: read locks and write
+ * locks. Read locks can be used in interrupt context, so while we
+ * hold the write lock, we must also block softclock interrupts (since
+ * the interrupt context is the timeout-driven schedcpu()).
+ *
+ * The proclist lock locks the following structures:
+ *
+ * allproc
+ * zombproc
+ * pidhashtbl
+ */
+struct lock proclist_lock;
+
+/*
* Locking of this proclist is special; it's accessed in a
* critical section of process exit, and thus locking it can't
* modify interrupt state. We use a simple spin lock for this
@@ -120,6 +173,8 @@
for (pd = proclists; pd->pd_list != NULL; pd++)
LIST_INIT(pd->pd_list);
+ lockinit(&proclist_lock, PZERO, "proclk", 0, 0);
+
LIST_INIT(&deadproc);
simple_lock_init(&deadproc_slock);
@@ -140,6 +195,85 @@
}
/*
+ * Acquire a read lock on the proclist.
+ */
+void
+proclist_lock_read(flags)
+ int flags;
+{
Home |
Main Index |
Thread Index |
Old Index