Page MenuHomeFreeBSD

D29005.id85580.diff
No OneTemporary

D29005.id85580.diff

diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -859,6 +859,7 @@
condvar.9 cv_wait_unlock.9 \
condvar.9 cv_wmesg.9
MLINKS+=config_intrhook.9 config_intrhook_disestablish.9 \
+ config_intrhook.9 config_intrhook_drain.9 \
config_intrhook.9 config_intrhook_establish.9 \
config_intrhook.9 config_intrhook_oneshot.9
MLINKS+=contigmalloc.9 contigmalloc_domainset.9 \
diff --git a/share/man/man9/config_intrhook.9 b/share/man/man9/config_intrhook.9
--- a/share/man/man9/config_intrhook.9
+++ b/share/man/man9/config_intrhook.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 10, 2017
+.Dd March 8, 2021
.Dt CONFIG_INTRHOOK 9
.Os
.Sh NAME
@@ -40,6 +40,8 @@
.Fn config_intrhook_establish "struct intr_config_hook *hook"
.Ft void
.Fn config_intrhook_disestablish "struct intr_config_hook *hook"
+.Ft int
+.Fn config_intrhook_drain "struct intr_config_hook *hook"
.Ft void
.Fn config_intrhook_oneshot "ich_func_t func" "void *arg"
.Sh DESCRIPTION
@@ -55,6 +57,23 @@
function removes the entry from the hook queue.
.Pp
The
+.Fn config_intrhook_drain
+function removes the entry from the hook queue in a safe way.
+If the hook is not currently active it removes
+.Fa hook
+from the hook queue and returns
+.Vt ICHS_QUEUED .
+If the hook is active, it waits for the hook to complete before returning
+.Vt ICHS_RUNNING .
+If the hook has previously completed, it returns
+.Vt ICHS_DONE .
+Because a
+.Vt config_intrhook
+is undefined prior to
+.Fn config_intrhook_establish ,
+this function may only be called after that function has returned.
+.Pp
+The
.Fn config_intrhook_oneshot
function schedules a function to be run as described for
.Fn config_intrhook_establish ;
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -138,6 +138,7 @@
while (next_to_notify != NULL) {
hook_entry = next_to_notify;
next_to_notify = STAILQ_NEXT(hook_entry, ich_links);
+ hook_entry->ich_state = ICHS_RUNNING;
mtx_unlock(&intr_config_hook_lock);
(*hook_entry->ich_func)(hook_entry->ich_arg);
mtx_lock(&intr_config_hook_lock);
@@ -199,6 +200,7 @@
STAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links);
if (next_to_notify == NULL)
next_to_notify = hook;
+ hook->ich_state = ICHS_QUEUED;
mtx_unlock(&intr_config_hook_lock);
if (cold == 0)
/*
@@ -226,12 +228,11 @@
config_intrhook_establish(&ohook->och_hook);
}
-void
-config_intrhook_disestablish(struct intr_config_hook *hook)
+static void
+config_intrhook_disestablish_locked(struct intr_config_hook *hook)
{
struct intr_config_hook *hook_entry;
- mtx_lock(&intr_config_hook_lock);
STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
if (hook_entry == hook)
break;
@@ -245,8 +246,51 @@
TSRELEASE("config hooks");
/* Wakeup anyone watching the list */
+ hook->ich_state = ICHS_DONE;
wakeup(&intr_config_hook_list);
+}
+
+void
+config_intrhook_disestablish(struct intr_config_hook *hook)
+{
+ mtx_lock(&intr_config_hook_lock);
+ config_intrhook_disestablish_locked(hook);
+ mtx_unlock(&intr_config_hook_lock);
+}
+
+int
+config_intrhook_drain(struct intr_config_hook *hook)
+{
+ mtx_lock(&intr_config_hook_lock);
+
+ /*
+ * The config hook has completed, so just return.
+ */
+ if (hook->ich_state == ICHS_DONE) {
+ mtx_unlock(&intr_config_hook_lock);
+ return (ICHS_DONE);
+ }
+
+ /*
+ * The config hook hasn't started running, just call disestablish.
+ */
+ if (hook->ich_state == ICHS_QUEUED) {
+ config_intrhook_disestablish_locked(hook);
+ mtx_unlock(&intr_config_hook_lock);
+ return (ICHS_QUEUED);
+ }
+
+ /*
+ * The config hook is running, so wait for it to complete and return.
+ */
+ while (hook->ich_state != ICHS_DONE) {
+ if (msleep(&intr_config_hook_list, &intr_config_hook_lock,
+ 0, "confhd", hz) == EWOULDBLOCK) {
+ // XXX do I whine?
+ }
+ }
mtx_unlock(&intr_config_hook_lock);
+ return (ICHS_RUNNING);
}
#ifdef DDB
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -467,13 +467,17 @@
struct intr_config_hook {
STAILQ_ENTRY(intr_config_hook) ich_links;
- uintptr_t ich_padding;
+ uintptr_t ich_state;
+#define ICHS_QUEUED 0x1
+#define ICHS_RUNNING 0x2
+#define ICHS_DONE 0x3
ich_func_t ich_func;
void *ich_arg;
};
int config_intrhook_establish(struct intr_config_hook *hook);
void config_intrhook_disestablish(struct intr_config_hook *hook);
+int config_intrhook_drain(struct intr_config_hook *hook);
void config_intrhook_oneshot(ich_func_t _func, void *_arg);
#endif /* !_SYS_KERNEL_H_*/

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 8:41 AM (8 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16358982
Default Alt Text
D29005.id85580.diff (4 KB)

Event Timeline