33#include <sys/kernel.h>
36#include <sys/malloc.h>
40#include <sys/eventhandler.h>
42static MALLOC_DEFINE(M_EVENTHANDLER,
"eventhandler",
"Event handler records");
45static TAILQ_HEAD(, eventhandler_list) eventhandler_lists;
46static int eventhandler_lists_initted = 0;
47static struct mtx eventhandler_mutex;
49struct eventhandler_entry_generic
51 struct eventhandler_entry ee;
63 TAILQ_INIT(&eventhandler_lists);
64 mtx_init(&eventhandler_mutex,
"eventhandler", NULL, MTX_DEF);
65 atomic_store_rel_int(&eventhandler_lists_initted, 1);
70static struct eventhandler_list *
73 struct eventhandler_list *list, *new_list;
80 mtx_unlock(&eventhandler_mutex);
82 new_list =
malloc(
sizeof(*new_list) + strlen(
name) + 1,
83 M_EVENTHANDLER, M_WAITOK | M_ZERO);
86 mtx_lock(&eventhandler_mutex);
89 free(new_list, M_EVENTHANDLER);
91 CTR2(KTR_EVH,
"%s: creating list \"%s\"", __func__,
name);
93 TAILQ_INIT(&list->el_entries);
94 list->el_name = (
char *)(list + 1);
95 strcpy(list->el_name,
name);
96 mtx_init(&list->el_lock, list->el_name,
"eventhandler list",
98 TAILQ_INSERT_HEAD(&eventhandler_lists, list, el_link);
108static eventhandler_tag
110 const char *
name, eventhandler_tag epn)
112 struct eventhandler_entry *ep;
114 KASSERT(eventhandler_lists_initted, (
"eventhandler registered too early"));
115 KASSERT(epn != NULL, (
"%s: cannot register NULL event", __func__));
119 mtx_lock(&eventhandler_mutex);
121 mtx_unlock(&eventhandler_mutex);
124 KASSERT(epn->ee_priority != EHE_DEAD_PRIORITY,
125 (
"%s: handler for %s registered with dead priority", __func__,
name));
128 CTR4(KTR_EVH,
"%s: adding item %p (function %p) to \"%s\"", __func__, epn,
129 ((
struct eventhandler_entry_generic *)epn)->func,
name);
131 TAILQ_FOREACH(ep, &list->el_entries, ee_link) {
132 if (ep->ee_priority != EHE_DEAD_PRIORITY &&
133 epn->ee_priority < ep->ee_priority) {
134 TAILQ_INSERT_BEFORE(ep, epn, ee_link);
139 TAILQ_INSERT_TAIL(&list->el_entries, epn, ee_link);
146 void *func,
void *arg,
int priority)
148 struct eventhandler_entry_generic *eg;
151 eg =
malloc(
sizeof(
struct eventhandler_entry_generic), M_EVENTHANDLER,
161struct eventhandler_entry_generic_vimage
163 struct eventhandler_entry ee;
164 vimage_iterator_func_t func;
165 struct eventhandler_entry_vimage v_ee;
169vimage_eventhandler_register(
struct eventhandler_list *list,
const char *
name,
170 void *func,
void *arg,
int priority, vimage_iterator_func_t iterfunc)
172 struct eventhandler_entry_generic_vimage *eg;
175 eg =
malloc(
sizeof(
struct eventhandler_entry_generic_vimage),
176 M_EVENTHANDLER, M_WAITOK | M_ZERO);
178 eg->v_ee.func = func;
179 eg->v_ee.ee_arg = arg;
180 eg->ee.ee_arg = &eg->v_ee;
191 struct eventhandler_entry *ep = tag;
193 EHL_LOCK_ASSERT(list, MA_OWNED);
196 if (list->el_runcount == 0) {
197 CTR3(KTR_EVH,
"%s: removing item %p from \"%s\"", __func__, ep,
199 TAILQ_REMOVE(&list->el_entries, ep, ee_link);
200 free(ep, M_EVENTHANDLER);
202 CTR3(KTR_EVH,
"%s: marking item %p from \"%s\" as dead", __func__,
204 ep->ee_priority = EHE_DEAD_PRIORITY;
208 if (list->el_runcount == 0) {
209 CTR2(KTR_EVH,
"%s: removing all items from \"%s\"", __func__,
211 while (!TAILQ_EMPTY(&list->el_entries)) {
212 ep = TAILQ_FIRST(&list->el_entries);
213 TAILQ_REMOVE(&list->el_entries, ep, ee_link);
214 free(ep, M_EVENTHANDLER);
217 CTR2(KTR_EVH,
"%s: marking all items from \"%s\" as dead",
218 __func__, list->el_name);
219 TAILQ_FOREACH(ep, &list->el_entries, ee_link)
220 ep->ee_priority = EHE_DEAD_PRIORITY;
223 while (wait && list->el_runcount > 0)
224 mtx_sleep(list, &list->el_lock, 0,
"evhrm", 0);
237 eventhandler_tag tag)
246static struct eventhandler_list *
249 struct eventhandler_list *list;
251 mtx_assert(&eventhandler_mutex, MA_OWNED);
252 TAILQ_FOREACH(list, &eventhandler_lists, el_link) {
253 if (!strcmp(
name, list->el_name))
262struct eventhandler_list *
265 struct eventhandler_list *list;
267 if (!eventhandler_lists_initted)
271 mtx_lock(&eventhandler_mutex);
275 mtx_unlock(&eventhandler_mutex);
286 struct eventhandler_entry *ep, *en;
289 CTR2(KTR_EVH,
"%s: pruning list \"%s\"", __func__, list->el_name);
290 EHL_LOCK_ASSERT(list, MA_OWNED);
291 TAILQ_FOREACH_SAFE(ep, &list->el_entries, ee_link, en) {
292 if (ep->ee_priority == EHE_DEAD_PRIORITY) {
293 TAILQ_REMOVE(&list->el_entries, ep, ee_link);
294 free(ep, M_EVENTHANDLER);
306struct eventhandler_list *
309 struct eventhandler_list *list;
311 KASSERT(eventhandler_lists_initted,
312 (
"eventhandler list created too early"));
314 mtx_lock(&eventhandler_mutex);
316 mtx_unlock(&eventhandler_mutex);
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void wakeup(const void *ident)
static struct eventhandler_list * _eventhandler_find_list(const char *name)
void eventhandler_prune_list(struct eventhandler_list *list)
static void eventhandler_init(void *dummy __unused)
void eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag)
static struct eventhandler_list * eventhandler_find_or_create_list(const char *name)
SYSINIT(eventhandlers, SI_SUB_EVENTHANDLER, SI_ORDER_FIRST, eventhandler_init, NULL)
static TAILQ_HEAD(eventhandler_list)
static void _eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag, bool wait)
void eventhandler_deregister_nowait(struct eventhandler_list *list, eventhandler_tag tag)
static MALLOC_DEFINE(M_EVENTHANDLER, "eventhandler", "Event handler records")
struct eventhandler_list * eventhandler_create_list(const char *name)
eventhandler_tag eventhandler_register(struct eventhandler_list *list, const char *name, void *func, void *arg, int priority)
static eventhandler_tag eventhandler_register_internal(struct eventhandler_list *list, const char *name, eventhandler_tag epn)
struct eventhandler_list * eventhandler_find_list(const char *name)