- Convert the per-eventhandler list mutex to a lockmgr lock so that it can
be safely held across an eventhandler function call. - Fix an instance of the head of an eventhandler list being read without the lock being held. - Break down and use a SYSINIT at the new SI_SUB_EVENTHANDLER to initialize the eventhandler global mutex and the eventhandler list of lists rather than using a non-MP safe initialization during the first call to eventhandler_register(). - Add in a KASSERT() to eventhandler_register() to ensure that we don't try to register an eventhandler before things have been initialized.
This commit is contained in:
parent
18f619abce
commit
06592dd188
@ -29,6 +29,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/eventhandler.h>
|
||||
|
||||
@ -45,6 +46,19 @@ struct eventhandler_entry_generic
|
||||
void (* func)(void);
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the eventhandler mutex and list.
|
||||
*/
|
||||
static void
|
||||
eventhandler_init(void *dummy __unused)
|
||||
{
|
||||
TAILQ_INIT(&eventhandler_lists);
|
||||
mtx_init(&eventhandler_mutex, "eventhandler", MTX_DEF);
|
||||
eventhandler_lists_initted = 1;
|
||||
}
|
||||
SYSINIT(eventhandlers, SI_SUB_EVENTHANDLER, SI_ORDER_FIRST, eventhandler_init,
|
||||
NULL)
|
||||
|
||||
/*
|
||||
* Insertion is O(n) due to the priority scan, but optimises to O(1)
|
||||
* if all priorities are identical.
|
||||
@ -56,12 +70,7 @@ eventhandler_register(struct eventhandler_list *list, char *name,
|
||||
struct eventhandler_entry_generic *eg;
|
||||
struct eventhandler_entry *ep;
|
||||
|
||||
/* avoid the need for a SYSINIT just to init the list */
|
||||
if (!eventhandler_lists_initted) {
|
||||
TAILQ_INIT(&eventhandler_lists);
|
||||
mtx_init(&eventhandler_mutex, "eventhandler", MTX_DEF);
|
||||
eventhandler_lists_initted = 1;
|
||||
}
|
||||
KASSERT(eventhandler_lists_initted, ("eventhandler registered too early"));
|
||||
|
||||
/* lock the eventhandler lists */
|
||||
mtx_enter(&eventhandler_mutex, MTX_DEF);
|
||||
@ -86,7 +95,7 @@ eventhandler_register(struct eventhandler_list *list, char *name,
|
||||
}
|
||||
if (!(list->el_flags & EHE_INITTED)) {
|
||||
TAILQ_INIT(&list->el_entries);
|
||||
mtx_init(&list->el_mutex, name, MTX_DEF);
|
||||
lockinit(&list->el_lock, PZERO, name, 0, 0);
|
||||
list->el_flags = EHE_INITTED;
|
||||
}
|
||||
|
||||
@ -101,7 +110,7 @@ eventhandler_register(struct eventhandler_list *list, char *name,
|
||||
eg->ee.ee_priority = priority;
|
||||
|
||||
/* sort it into the list */
|
||||
mtx_enter(&list->el_mutex, MTX_DEF);
|
||||
lockmgr(&list->el_lock, LK_EXCLUSIVE, NULL, CURPROC);
|
||||
for (ep = TAILQ_FIRST(&list->el_entries);
|
||||
ep != NULL;
|
||||
ep = TAILQ_NEXT(ep, ee_link)) {
|
||||
@ -112,7 +121,7 @@ eventhandler_register(struct eventhandler_list *list, char *name,
|
||||
}
|
||||
if (ep == NULL)
|
||||
TAILQ_INSERT_TAIL(&list->el_entries, &eg->ee, ee_link);
|
||||
mtx_exit(&list->el_mutex, MTX_DEF);
|
||||
lockmgr(&list->el_lock, LK_RELEASE, NULL, CURPROC);
|
||||
mtx_exit(&eventhandler_mutex, MTX_DEF);
|
||||
return(&eg->ee);
|
||||
}
|
||||
@ -123,7 +132,7 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag)
|
||||
struct eventhandler_entry *ep = tag;
|
||||
|
||||
/* XXX insert diagnostic check here? */
|
||||
mtx_enter(&list->el_mutex, MTX_DEF);
|
||||
lockmgr(&list->el_lock, LK_EXCLUSIVE, NULL, CURPROC);
|
||||
if (ep != NULL) {
|
||||
/* remove just this entry */
|
||||
TAILQ_REMOVE(&list->el_entries, ep, ee_link);
|
||||
@ -136,7 +145,7 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag)
|
||||
free(ep, M_EVENTHANDLER);
|
||||
}
|
||||
}
|
||||
mtx_exit(&list->el_mutex, MTX_DEF);
|
||||
lockmgr(&list->el_lock, LK_RELEASE, NULL, CURPROC);
|
||||
}
|
||||
|
||||
struct eventhandler_list *
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define SYS_EVENTHANDLER_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/lock.h>
|
||||
|
||||
struct eventhandler_entry
|
||||
{
|
||||
@ -44,7 +44,7 @@ struct eventhandler_list
|
||||
char *el_name;
|
||||
int el_flags;
|
||||
#define EHE_INITTED (1<<0)
|
||||
struct mtx el_mutex;
|
||||
struct lock el_lock;
|
||||
TAILQ_ENTRY(eventhandler_list) el_link;
|
||||
TAILQ_HEAD(,eventhandler_entry) el_entries;
|
||||
};
|
||||
@ -77,18 +77,18 @@ struct __hack
|
||||
#define EVENTHANDLER_FAST_INVOKE(name, args...) \
|
||||
do { \
|
||||
struct eventhandler_list *_el = &Xeventhandler_list_ ## name ; \
|
||||
struct eventhandler_entry *_ep = TAILQ_FIRST(&(_el->el_entries)); \
|
||||
struct eventhandler_entry *_en; \
|
||||
struct eventhandler_entry *_ep, *_en; \
|
||||
\
|
||||
if (_el->el_flags & EHE_INITTED) { \
|
||||
lockmgr(&_el->el_lock, LK_EXCLUSIVE, NULL, CURPROC); \
|
||||
_ep = TAILQ_FIRST(&(_el->el_entries)); \
|
||||
while (_ep != NULL) { \
|
||||
mtx_enter(&_el->el_mutex, MTX_DEF); \
|
||||
_en = TAILQ_NEXT(_ep, ee_link); \
|
||||
mtx_exit(&_el->el_mutex, MTX_DEF); \
|
||||
((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , \
|
||||
## args); \
|
||||
_ep = _en; \
|
||||
} \
|
||||
lockmgr(&_el->el_lock, LK_RELEASE, NULL, CURPROC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -120,17 +120,15 @@ do { \
|
||||
\
|
||||
if (((_el = eventhandler_find_list(#name)) != NULL) && \
|
||||
(_el->el_flags & EHE_INITTED)) { \
|
||||
mtx_enter(&_el->el_mutex, MTX_DEF); \
|
||||
lockmgr(&_el->el_lock, LK_EXCLUSIVE, NULL, CURPROC); \
|
||||
_ep = TAILQ_FIRST(&(_el->el_entries)); \
|
||||
mtx_exit(&_el->el_mutex, MTX_DEF); \
|
||||
while (_ep != NULL) { \
|
||||
mtx_enter(&_el->el_mutex, MTX_DEF); \
|
||||
_en = TAILQ_NEXT(_ep, ee_link); \
|
||||
mtx_exit(&_el->el_mutex, MTX_DEF); \
|
||||
((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , \
|
||||
## args); \
|
||||
_ep = _en; \
|
||||
} \
|
||||
lockmgr(&_el->el_lock, LK_RELEASE, NULL, CURPROC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -114,6 +114,7 @@ enum sysinit_sub_id {
|
||||
SI_SUB_KMEM = 0x1800000, /* kernel memory*/
|
||||
SI_SUB_KVM_RSRC = 0x1A00000, /* kvm operational limits*/
|
||||
SI_SUB_LOCK = 0x1B00000, /* lockmgr locks */
|
||||
SI_SUB_EVENTHANDLER = 0x1C00000, /* eventhandler init */
|
||||
SI_SUB_CPU = 0x2000000, /* CPU resource(s)*/
|
||||
SI_SUB_KLD = 0x2100000, /* KLD and module setup */
|
||||
SI_SUB_INTRINSIC = 0x2200000, /* proc 0*/
|
||||
|
Loading…
Reference in New Issue
Block a user