summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_autoconf.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-07-19 19:08:35 +0000
committerrwatson <rwatson@FreeBSD.org>2008-07-19 19:08:35 +0000
commitb53b96f01c70c1709c4667d091b1d7ec76b1c61a (patch)
tree80d95d2e6a19901039ba2fd68b60a34935fec11e /sys/kern/subr_autoconf.c
parentbf16f6ee0bd479475bbc88870d8287449dded845 (diff)
downloadFreeBSD-src-b53b96f01c70c1709c4667d091b1d7ec76b1c61a.zip
FreeBSD-src-b53b96f01c70c1709c4667d091b1d7ec76b1c61a.tar.gz
Rather than simply waiting silently and indefinitely for all
interrupt-driven configuration handlers to complete, print out a diagnostic message every 60 second indicating which handlers are still running. Do this at most 5 times per run so as to avoid scrolling out any useful information from the kernel message buffer. The interval of 60 seconds was selected based on a best guess as to the nature of "long enough" and may want to be tuned higher or lower depending on real-world tolerances. MFC after: 3 days Discussed with: scottl
Diffstat (limited to 'sys/kern/subr_autoconf.c')
-rw-r--r--sys/kern/subr_autoconf.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index 9bb1619..3e317ad 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/systm.h>
@@ -60,11 +61,36 @@ MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF);
/* ARGSUSED */
static void run_interrupt_driven_config_hooks(void *dummy);
+/*
+ * If we wait too long for an interrupt-driven config hook to return, print
+ * a diagnostic.
+ */
+#define WARNING_INTERVAL_SECS 60
+static void
+run_interrupt_driven_config_hooks_warning(int warned)
+{
+ struct intr_config_hook *hook_entry;
+ char namebuf[64];
+ long offset;
+
+ printf("run_interrupt_driven_hooks: still waiting after %d seconds "
+ "for", warned * WARNING_INTERVAL_SECS);
+ TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) {
+ if (linker_search_symbol_name((caddr_t)hook_entry->ich_func,
+ namebuf, sizeof(namebuf), &offset) == 0)
+ printf(" %s", namebuf);
+ else
+ printf(" %p", hook_entry->ich_func);
+ }
+ printf("\n");
+}
+
static void
run_interrupt_driven_config_hooks(dummy)
void *dummy;
{
struct intr_config_hook *hook_entry, *next_entry;
+ int warned;
mtx_lock(&intr_config_hook_lock);
TAILQ_FOREACH_SAFE(hook_entry, &intr_config_hook_list, ich_links,
@@ -74,9 +100,16 @@ run_interrupt_driven_config_hooks(dummy)
mtx_lock(&intr_config_hook_lock);
}
+ warned = 0;
while (!TAILQ_EMPTY(&intr_config_hook_list)) {
- msleep(&intr_config_hook_list, &intr_config_hook_lock, PCONFIG,
- "conifhk", 0);
+ if (msleep(&intr_config_hook_list, &intr_config_hook_lock,
+ PCONFIG, "conifhk", WARNING_INTERVAL_SECS * hz) ==
+ EWOULDBLOCK && warned < 5) {
+ mtx_unlock(&intr_config_hook_lock);
+ warned++;
+ run_interrupt_driven_config_hooks_warning(warned);
+ mtx_lock(&intr_config_hook_lock);
+ }
}
mtx_unlock(&intr_config_hook_lock);
}
@@ -135,7 +168,6 @@ config_intrhook_disestablish(hook)
#ifdef DDB
#include <ddb/ddb.h>
-#include <sys/linker.h>
DB_SHOW_COMMAND(conifhk, db_show_conifhk)
{
OpenPOWER on IntegriCloud