Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Define a set of new kernel locking primitives to implement t...



details:   https://anonhg.NetBSD.org/src/rev/de32dcd51fa2
branches:  trunk
changeset: 757250:de32dcd51fa2
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Sat Aug 21 13:17:31 2010 +0000

description:
Define a set of new kernel locking primitives to implement the recursive
kernconfig_mutex.  Update module subsystem to use this mutex rather than
its own internal (non-recursive) mutex.  Make module_autoload() do its
own locking to be consistent with the rest of the module_xxx() calls.
Update module(9) man page appropriately.

As discussed on tech-kern over the last few weeks.

Welcome to NetBSD 5.99.39 !

diffstat:

 share/man/man9/module.9 |   50 ++++++++++++-----
 sys/conf/files          |    3 +-
 sys/kern/init_main.c    |    5 +-
 sys/kern/kern_cfglock.c |  101 +++++++++++++++++++++++++++++++++++
 sys/kern/kern_module.c  |  135 ++++++++++++++++++++++++++---------------------
 sys/sys/module.h        |    3 +-
 sys/sys/param.h         |    4 +-
 sys/sys/systm.h         |    7 ++-
 8 files changed, 224 insertions(+), 84 deletions(-)

diffs (truncated from 716 to 300 lines):

diff -r 95397848b9d9 -r de32dcd51fa2 share/man/man9/module.9
--- a/share/man/man9/module.9   Sat Aug 21 13:12:15 2010 +0000
+++ b/share/man/man9/module.9   Sat Aug 21 13:17:31 2010 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: module.9,v 1.17 2010/08/18 01:56:45 pgoyette Exp $
+.\"    $NetBSD: module.9,v 1.18 2010/08/21 13:17:32 pgoyette Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd August 17, 2010
+.Dd August XXX, 2010
 .Dt MODULE 9
 .Os
 .Sh NAME
@@ -86,6 +86,8 @@
 .Vt modinfo_t
 type resides within the module itself, and contains module header info.
 .El
+.Pp
+The module subsystem is protected by the global kernconfig_mutex.
 .Sh FUNCTIONS
 .Bl -tag -width abcd
 .It Fn MODULE "class" "name" "required"
@@ -362,21 +364,37 @@
 Until this routine is called, modules can only be loaded if they were
 built-in to the kernel image or provided by the boot loader.
 .El
-.Sh LOCK PROTOCOL
-The
-.Nm
-subsystem is protected with the global
-.Vt module_mutex .
-This
-.Xr mutex 9
-must be acquired before calling any of these routines.
-As an exception, the
+.Sh PROGRAMMING CONSIDERATIONS
+The module subsystem is designed to be called recursively, but only within
+a single lwp.
+This permits one module's
+.Fn modcmd
+routine to load or unload other modules.
+.Pp
+A module is not permitted to load or unload itself.
+Attempts to load or unload a module from within its own
+.Fn modcmd
+routine will fail with
+.Er EEXIST
+or
+.Er EBUSY
+respectively.
+.Pp
+Although a module can be loaded by either
 .Fn module_load
-routine acquires the mutex itself, so one does not need to acquire it
-before calling
-.Fn module_load .
-Loading of a module and its required modules occurs as an atomic
-operation, and either completely succeeds or completely fails.
+or
+.Fn module_autoload
+it is not possible for the module's
+.Fn modcmd
+routine to distinguish between the two methods.
+Any module which needs to ensure that it does not get auto-unloaded must
+either handle the
+.Dv MODULE_CMD_AUTOUNLOAD
+command in its
+.Fn modcmd
+routine, or use
+.Fn module_hold
+to increment its reference count.
 .Sh CODE REFERENCES
 This section describes places within the
 .Nx
diff -r 95397848b9d9 -r de32dcd51fa2 sys/conf/files
--- a/sys/conf/files    Sat Aug 21 13:12:15 2010 +0000
+++ b/sys/conf/files    Sat Aug 21 13:17:31 2010 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.992 2010/07/07 01:09:39 chs Exp $
+#      $NetBSD: files,v 1.993 2010/08/21 13:17:32 pgoyette Exp $
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
 version        20100430
@@ -1434,6 +1434,7 @@
 file   kern/init_sysent.c
 file   kern/kern_acct.c
 file   kern/kern_auth.c
+file   kern/kern_cfglock.c
 file   kern/kern_clock.c
 file   kern/kern_condvar.c
 file   kern/kern_core.c                coredump
diff -r 95397848b9d9 -r de32dcd51fa2 sys/kern/init_main.c
--- a/sys/kern/init_main.c      Sat Aug 21 13:12:15 2010 +0000
+++ b/sys/kern/init_main.c      Sat Aug 21 13:17:31 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: init_main.c,v 1.422 2010/06/26 07:23:57 pgoyette Exp $ */
+/*     $NetBSD: init_main.c,v 1.423 2010/08/21 13:17:31 pgoyette Exp $ */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.422 2010/06/26 07:23:57 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.423 2010/08/21 13:17:31 pgoyette Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipsec.h"
@@ -303,6 +303,7 @@
        kernel_lock_init();
        once_init();
        mutex_init(&cpu_lock, MUTEX_DEFAULT, IPL_NONE);
+       kernconfig_lock_init();
 
        /* Initialize the device switch tables. */
        devsw_init();
diff -r 95397848b9d9 -r de32dcd51fa2 sys/kern/kern_cfglock.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/kern/kern_cfglock.c   Sat Aug 21 13:17:31 2010 +0000
@@ -0,0 +1,101 @@
+/*     $NetBSD: kern_cfglock.c,v 1.1 2010/08/21 13:17:31 pgoyette Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2006, 2007, 2008, 2009 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, and by Andrew Doran.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: kern_cfglock.c,v 1.1 2010/08/21 13:17:31 pgoyette Exp $");
+
+#include <sys/param.h>
+#include <sys/cpu.h>
+#include <sys/mutex.h>
+#include <sys/lwp.h>
+#include <sys/systm.h>
+
+static kmutex_t kernconfig_mutex;
+static lwp_t *kernconfig_lwp;
+static int kernconfig_recurse;
+
+/*
+ * Functions for manipulating the kernel configuration lock.  This
+ * recursive lock should be used to protect all additions and removals
+ * of kernel functionality, such as device configuration and loading
+ * of modular kernel components.
+ */
+
+void
+kernconfig_lock_init(void)
+{
+
+       mutex_init(&kernconfig_mutex, MUTEX_DEFAULT, IPL_NONE);
+       kernconfig_lwp = NULL;
+       kernconfig_recurse = 0;
+}
+
+void
+kernconfig_lock(void)
+{
+       lwp_t   *my_lwp;
+
+       /*
+        * It's OK to check this unlocked, since it could only be set to
+        * curlwp by the current thread itself, and not by an interrupt
+        * or any other LWP.
+        */
+       KASSERT(!cpu_intr_p());
+       my_lwp = curlwp;
+       if (kernconfig_lwp == my_lwp) {
+               kernconfig_recurse++;
+               KASSERT(kernconfig_recurse > 1);
+       } else {
+               mutex_enter(&kernconfig_mutex);
+               kernconfig_lwp = my_lwp;
+               kernconfig_recurse = 1;
+       }
+}
+
+void
+kernconfig_unlock(void)
+{
+
+       KASSERT(kernconfig_is_held());
+       KASSERT(kernconfig_recurse != 0);
+       if (--kernconfig_recurse == 0) {
+               kernconfig_lwp = NULL;
+               mutex_exit(&kernconfig_mutex);
+       }
+}
+
+bool
+kernconfig_is_held(void)
+{
+
+       return mutex_owned(&kernconfig_mutex);
+}
diff -r 95397848b9d9 -r de32dcd51fa2 sys/kern/kern_module.c
--- a/sys/kern/kern_module.c    Sat Aug 21 13:12:15 2010 +0000
+++ b/sys/kern/kern_module.c    Sat Aug 21 13:17:31 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_module.c,v 1.71 2010/08/11 12:04:49 pgoyette Exp $        */
+/*     $NetBSD: kern_module.c,v 1.72 2010/08/21 13:17:31 pgoyette Exp $        */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.71 2010/08/11 12:04:49 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.72 2010/08/21 13:17:31 pgoyette Exp $");
 
 #define _MODULE_INTERNAL
 
@@ -72,7 +72,6 @@
 static int     module_autoload_on = 1;
 u_int          module_count;
 u_int          module_builtinlist;
-kmutex_t       module_lock;
 u_int          module_autotime = 10;
 u_int          module_gen = 1;
 static kcondvar_t module_thread_cv;
@@ -223,7 +222,7 @@
                modp[i] = module_newmodule(MODULE_SOURCE_KERNEL);
                modp[i]->mod_info = mip[i+mipskip];
        }
-       mutex_enter(&module_lock);
+       kernconfig_lock();
 
        /* do this in three stages for error recovery and atomicity */
 
@@ -263,7 +262,7 @@
        }
 
  out:
-       mutex_exit(&module_lock);
+       kernconfig_unlock();
        if (rv != 0) {
                for (i = 0; i < nmodinfo; i++) {
                        if (modp[i])
@@ -291,13 +290,13 @@
                if (rv)
                        return rv;
 
-               mutex_enter(&module_lock);
+               kernconfig_lock();
                rv = module_do_unload(mi->mi_name, true);
                if (rv) {
                        goto out;
                }
        } else {
-               mutex_enter(&module_lock);
+               kernconfig_lock();
        }
        TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
                if (strcmp(mod->mod_info->mi_name, mi->mi_name) == 0)
@@ -312,7 +311,7 @@
        }
 
  out:
-       mutex_exit(&module_lock);
+       kernconfig_unlock();
        return rv;
 }
 
@@ -332,7 +331,6 @@
        if (module_map == NULL) {
                module_map = kernel_map;
        }



Home | Main Index | Thread Index | Old Index