aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_autoconf.c
diff options
context:
space:
mode:
authorJustin T. Gibbs <gibbs@FreeBSD.org>1997-09-21 22:00:25 +0000
committerJustin T. Gibbs <gibbs@FreeBSD.org>1997-09-21 22:00:25 +0000
commitab36c06737cfd52b6f1999903ee7f91014ac51de (patch)
tree9a66b11a4142135b5168ca62c728affa25f9aefe /sys/kern/subr_autoconf.c
parent35442183351c76bca81db6ef96104c65c42a46ca (diff)
downloadsrc-ab36c06737cfd52b6f1999903ee7f91014ac51de.tar.gz
src-ab36c06737cfd52b6f1999903ee7f91014ac51de.zip
init_main.c subr_autoconf.c:
Add support for "interrupt driven configuration hooks". A component of the kernel can register a hook, most likely during auto-configuration, and receive a callback once interrupt services are available. This callback will occur before the root and dump devices are configured, so the configuration task can affect the selection of those two devices or complete any tasks that need to be performed prior to launching init. System boot is posponed so long as a hook is registered. The hook owner is responsible for removing the hook once their task is complete or the system boot can continue. kern_acct.c kern_clock.c kern_exit.c kern_synch.c kern_time.c: Change the interface and implementation for the kernel callout service. The new implemntaion is based on the work of Adam M. Costello and George Varghese, published in a technical report entitled "Redesigning the BSD Callout and Timer Facilities". The interface used in FreeBSD is a little different than the one outlined in the paper. The new function prototypes are: struct callout_handle timeout(void (*func)(void *), void *arg, int ticks); void untimeout(void (*func)(void *), void *arg, struct callout_handle handle); If a client wishes to remove a timeout, it must store the callout_handle returned by timeout and pass it to untimeout. The new implementation gives 0(1) insert and removal of callouts making this interface scale well even for applications that keep 100s of callouts outstanding. See the updated timeout.9 man page for more details.
Notes
Notes: svn path=/head/; revision=29680
Diffstat (limited to 'sys/kern/subr_autoconf.c')
-rw-r--r--sys/kern/subr_autoconf.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index f48ce99f0a37..2b72584273ab 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -41,10 +41,13 @@
*
* @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93
*
- * $Id$
+ * $Id: subr_autoconf.c,v 1.4 1997/02/22 09:39:15 peter Exp $
*/
#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
@@ -52,6 +55,7 @@
* Autoconfiguration subroutines.
*/
+#ifdef UNUSED
/*
* ioconf.c exports exactly two names: cfdata and cfroots. All system
* devices and drivers are found via these tables.
@@ -340,3 +344,78 @@ evcnt_attach(dev, name, ev)
*nextp = ev;
nextp = &ev->ev_next;
}
+
+#endif
+
+/*
+ * "Interrupt driven config" functions.
+ */
+static TAILQ_HEAD(, intr_config_hook) intr_config_hook_list =
+ TAILQ_HEAD_INITIALIZER(intr_config_hook_list);
+
+
+/* ARGSUSED */
+static void run_interrupt_driven_config_hooks __P((void *dummy));
+static void
+run_interrupt_driven_config_hooks(dummy)
+ void *dummy;
+{
+ struct intr_config_hook *hook;
+
+ for (hook = intr_config_hook_list.tqh_first; hook != NULL;
+ hook = hook->ich_links.tqe_next) {
+ (*hook->ich_func)(hook->ich_arg);
+ }
+
+ while (intr_config_hook_list.tqh_first != NULL) {
+ tsleep(&intr_config_hook_list, PCONFIG, "conifhk", 0);
+ }
+}
+SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST,
+ run_interrupt_driven_config_hooks, NULL)
+
+/*
+ * Register a hook that will be called after "cold"
+ * autoconfiguration is complete and interrupts can
+ * be used to complete initialization.
+ */
+int
+config_intrhook_establish(hook)
+ struct intr_config_hook *hook;
+{
+ struct intr_config_hook *hook_entry;
+
+ for (hook_entry = intr_config_hook_list.tqh_first; hook_entry != NULL;
+ hook_entry = hook_entry->ich_links.tqe_next)
+ if (hook_entry == hook)
+ break;
+ if (hook_entry != NULL) {
+ printf("config_intrhook_establish: establishing an "
+ "already established hook.\n");
+ return (1);
+ }
+ TAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links);
+ if (cold == 0)
+ /* XXX Sufficient for LKMs loaded after initial config??? */
+ run_interrupt_driven_config_hooks(NULL);
+ return (0);
+}
+
+void
+config_intrhook_disestablish(hook)
+ struct intr_config_hook *hook;
+{
+ struct intr_config_hook *hook_entry;
+
+ for (hook_entry = intr_config_hook_list.tqh_first; hook_entry != NULL;
+ hook_entry = hook_entry->ich_links.tqe_next)
+ if (hook_entry == hook)
+ break;
+ if (hook_entry == NULL)
+ panic("config_intrhook_disestablish: disestablishing an "
+ "unestablished hook");
+
+ TAILQ_REMOVE(&intr_config_hook_list, hook, ich_links);
+ /* Wakeup anyone watching the list */
+ wakeup(&intr_config_hook_list);
+}