Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108989433
D29005.id85580.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D29005.id85580.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D29005: config_intrhook: provide config_intrhook_drain
Attached
Detach File
Event Timeline
Log In to Comment