45#include <sys/kernel.h>
46#include <sys/linker.h>
48#include <sys/malloc.h>
60 STAILQ_HEAD_INITIALIZER(intr_config_hook_list);
61static struct intr_config_hook *next_to_notify;
62static struct mtx intr_config_hook_lock;
63MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock,
"intr config", MTX_DEF);
71struct oneshot_config_hook {
72 struct intr_config_hook
81 struct oneshot_config_hook *ohook;
84 ohook->och_func(ohook->och_arg);
86 free(ohook, M_DEVBUF);
93#define WARNING_INTERVAL_SECS 60
97 struct intr_config_hook *hook_entry;
102 printf(
"run_interrupt_driven_hooks: still waiting after %d "
104 STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) {
106 (caddr_t)hook_entry->ich_func, namebuf,
107 sizeof(namebuf), &offset) == 0)
110 printf(
" %p", hook_entry->ich_func);
115 (
"run_interrupt_driven_config_hooks: waited too long"));
122 struct intr_config_hook *hook_entry;
125 mtx_lock(&intr_config_hook_lock);
134 mtx_unlock(&intr_config_hook_lock);
139 while (next_to_notify != NULL) {
140 hook_entry = next_to_notify;
141 next_to_notify = STAILQ_NEXT(hook_entry, ich_links);
142 hook_entry->ich_state = ICHS_RUNNING;
143 mtx_unlock(&intr_config_hook_lock);
144 (*hook_entry->ich_func)(hook_entry->ich_arg);
145 mtx_lock(&intr_config_hook_lock);
149 mtx_unlock(&intr_config_hook_lock);
161 TSWAIT(
"config hooks");
162 mtx_lock(&intr_config_hook_lock);
164 while (!STAILQ_EMPTY(&intr_config_hook_list)) {
165 if (msleep(&intr_config_hook_list, &intr_config_hook_lock,
168 mtx_unlock(&intr_config_hook_lock);
171 mtx_lock(&intr_config_hook_lock);
174 mtx_unlock(&intr_config_hook_lock);
175 TSUNWAIT(
"config hooks");
178SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST,
189 struct intr_config_hook *hook_entry;
191 TSHOLD(
"config hooks");
192 mtx_lock(&intr_config_hook_lock);
193 STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
194 if (hook_entry == hook)
196 if (hook_entry != NULL) {
197 mtx_unlock(&intr_config_hook_lock);
198 printf(
"config_intrhook_establish: establishing an "
199 "already established hook.\n");
202 STAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links);
203 if (next_to_notify == NULL)
204 next_to_notify = hook;
205 hook->ich_state = ICHS_QUEUED;
206 mtx_unlock(&intr_config_hook_lock);
223 struct oneshot_config_hook *ohook;
225 ohook =
malloc(
sizeof(*ohook), M_DEVBUF, M_WAITOK);
226 ohook->och_func = func;
227 ohook->och_arg = arg;
229 ohook->och_hook.ich_arg = ohook;
236 struct intr_config_hook *hook_entry;
238 STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
239 if (hook_entry == hook)
241 if (hook_entry == NULL)
242 panic(
"config_intrhook_disestablish: disestablishing an "
243 "unestablished hook");
245 if (next_to_notify == hook)
246 next_to_notify = STAILQ_NEXT(hook, ich_links);
247 STAILQ_REMOVE(&intr_config_hook_list, hook, intr_config_hook, ich_links);
248 TSRELEASE(
"config hooks");
251 hook->ich_state = ICHS_DONE;
252 wakeup(&intr_config_hook_list);
258 mtx_lock(&intr_config_hook_lock);
260 mtx_unlock(&intr_config_hook_lock);
266 mtx_lock(&intr_config_hook_lock);
271 if (hook->ich_state == ICHS_DONE) {
272 mtx_unlock(&intr_config_hook_lock);
279 if (hook->ich_state == ICHS_QUEUED) {
281 mtx_unlock(&intr_config_hook_lock);
282 return (ICHS_QUEUED);
288 while (hook->ich_state != ICHS_DONE) {
289 if (msleep(&intr_config_hook_list, &intr_config_hook_lock,
290 0,
"confhd",
hz) == EWOULDBLOCK) {
294 mtx_unlock(&intr_config_hook_lock);
295 return (ICHS_RUNNING);
301DB_SHOW_COMMAND(conifhk, db_show_conifhk)
303 struct intr_config_hook *hook_entry;
307 STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) {
309 (caddr_t)hook_entry->ich_func, namebuf,
sizeof(namebuf),
311 db_printf(
"hook: %p at %s+%#lx arg: %p\n",
312 hook_entry->ich_func, namebuf, offset,
313 hook_entry->ich_arg);
315 db_printf(
"hook: %p at ??+?? arg %p\n",
316 hook_entry->ich_func, hook_entry->ich_arg);
MTX_SYSINIT(et_eventtimers_init, &et_eventtimers_mtx, "et_mtx", MTX_DEF)
int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
int linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void panic(const char *fmt,...)
void wakeup(const void *ident)
#define WARNING_INTERVAL_SECS
void config_intrhook_disestablish(struct intr_config_hook *hook)
static STAILQ_HEAD(MTX_SYSINIT(intr_config_hook)
static void config_intrhook_disestablish_locked(struct intr_config_hook *hook)
static void boot_run_interrupt_driven_config_hooks(void *dummy)
static void config_intrhook_oneshot_func(void *arg)
void config_intrhook_oneshot(ich_func_t func, void *arg)
int config_intrhook_drain(struct intr_config_hook *hook)
int config_intrhook_establish(struct intr_config_hook *hook)
static void run_interrupt_driven_config_hooks()
SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST, boot_run_interrupt_driven_config_hooks, NULL)
static void run_interrupt_driven_config_hooks_warning(int warned)
int printf(const char *fmt,...)