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