diff options
author | Justin T. Gibbs <gibbs@FreeBSD.org> | 1997-09-21 22:00:25 +0000 |
---|---|---|
committer | Justin T. Gibbs <gibbs@FreeBSD.org> | 1997-09-21 22:00:25 +0000 |
commit | ab36c06737cfd52b6f1999903ee7f91014ac51de (patch) | |
tree | 9a66b11a4142135b5168ca62c728affa25f9aefe /sys/kern/subr_autoconf.c | |
parent | 35442183351c76bca81db6ef96104c65c42a46ca (diff) | |
download | src-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.c | 81 |
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); +} |