diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-07-19 19:08:35 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-07-19 19:08:35 +0000 |
commit | b53b96f01c70c1709c4667d091b1d7ec76b1c61a (patch) | |
tree | 80d95d2e6a19901039ba2fd68b60a34935fec11e /sys/kern/subr_autoconf.c | |
parent | bf16f6ee0bd479475bbc88870d8287449dded845 (diff) | |
download | FreeBSD-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.c | 38 |
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) { |