summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_autoconf.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-07-19 18:53:56 +0000
committerjhb <jhb@FreeBSD.org>2006-07-19 18:53:56 +0000
commit70424c0f306a3e1040c5ff78f5d0b2275689cbb9 (patch)
treee67c5551e33b89782d526060e8751242b595a51c /sys/kern/subr_autoconf.c
parent7863d70730bd1f7afe32c78e631b91fc0c2dd01e (diff)
downloadFreeBSD-src-70424c0f306a3e1040c5ff78f5d0b2275689cbb9.zip
FreeBSD-src-70424c0f306a3e1040c5ff78f5d0b2275689cbb9.tar.gz
Add a mutex to protect the list of interrupt config hooks. We do assume
that the only remove hook operation that can occur while processing the hooks is to remove the currently executing hook. This should be safe as the existing code has assumed this already for a long time now. Reviewed by: scottl MFC after: 1 week
Diffstat (limited to 'sys/kern/subr_autoconf.c')
-rw-r--r--sys/kern/subr_autoconf.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index d40f1e4..067e155 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/systm.h>
/*
@@ -50,26 +52,32 @@ __FBSDID("$FreeBSD$");
*/
static TAILQ_HEAD(, intr_config_hook) intr_config_hook_list =
TAILQ_HEAD_INITIALIZER(intr_config_hook_list);
-
+static struct mtx intr_config_hook_lock;
+MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF);
/* ARGSUSED */
static void run_interrupt_driven_config_hooks(void *dummy);
+
static void
run_interrupt_driven_config_hooks(dummy)
void *dummy;
{
struct intr_config_hook *hook_entry, *next_entry;
- for (hook_entry = TAILQ_FIRST(&intr_config_hook_list);
- hook_entry != NULL;
- hook_entry = next_entry) {
+ mtx_lock(&intr_config_hook_lock);
+ TAILQ_FOREACH_SAFE(hook_entry, &intr_config_hook_list, ich_links,
+ next_entry) {
next_entry = TAILQ_NEXT(hook_entry, ich_links);
+ mtx_unlock(&intr_config_hook_lock);
(*hook_entry->ich_func)(hook_entry->ich_arg);
+ mtx_lock(&intr_config_hook_lock);
}
while (!TAILQ_EMPTY(&intr_config_hook_list)) {
- tsleep(&intr_config_hook_list, PCONFIG, "conifhk", 0);
+ msleep(&intr_config_hook_list, &intr_config_hook_lock, PCONFIG,
+ "conifhk", 0);
}
+ mtx_unlock(&intr_config_hook_lock);
}
SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST,
run_interrupt_driven_config_hooks, NULL)
@@ -85,17 +93,18 @@ config_intrhook_establish(hook)
{
struct intr_config_hook *hook_entry;
- for (hook_entry = TAILQ_FIRST(&intr_config_hook_list);
- hook_entry != NULL;
- hook_entry = TAILQ_NEXT(hook_entry, ich_links))
+ mtx_lock(&intr_config_hook_lock);
+ TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
if (hook_entry == hook)
break;
if (hook_entry != NULL) {
+ mtx_unlock(&intr_config_hook_lock);
printf("config_intrhook_establish: establishing an "
"already established hook.\n");
return (1);
}
TAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links);
+ mtx_unlock(&intr_config_hook_lock);
if (cold == 0)
/* XXX Sufficient for modules loaded after initial config??? */
run_interrupt_driven_config_hooks(NULL);
@@ -108,9 +117,8 @@ config_intrhook_disestablish(hook)
{
struct intr_config_hook *hook_entry;
- for (hook_entry = TAILQ_FIRST(&intr_config_hook_list);
- hook_entry != NULL;
- hook_entry = TAILQ_NEXT(hook_entry, ich_links))
+ mtx_lock(&intr_config_hook_lock);
+ TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
if (hook_entry == hook)
break;
if (hook_entry == NULL)
@@ -118,6 +126,8 @@ config_intrhook_disestablish(hook)
"unestablished hook");
TAILQ_REMOVE(&intr_config_hook_list, hook, ich_links);
+
/* Wakeup anyone watching the list */
wakeup(&intr_config_hook_list);
+ mtx_unlock(&intr_config_hook_lock);
}
OpenPOWER on IntegriCloud