From a4bf8740bb46d337eb18ae335c2f3b023098c63d Mon Sep 17 00:00:00 2001 From: msmith Date: Fri, 22 Sep 2000 03:17:35 +0000 Subject: Make the EVENTHANDLER mechanism MP-safe. Events can now be invoked without holding the Giant lock. --- sys/kern/subr_eventhandler.c | 24 +++++++++++++-- sys/sys/eventhandler.h | 73 ++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 30 deletions(-) diff --git a/sys/kern/subr_eventhandler.c b/sys/kern/subr_eventhandler.c index c23441d..1b9b739 100644 --- a/sys/kern/subr_eventhandler.c +++ b/sys/kern/subr_eventhandler.c @@ -58,9 +58,13 @@ eventhandler_register(struct eventhandler_list *list, char *name, /* 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; } + /* lock the eventhandler lists */ + mtx_enter(&eventhandler_mutex, MTX_DEF); + /* Do we need to find/create the (slow) list? */ if (list == NULL) { /* look for a matching, existing list */ @@ -69,8 +73,10 @@ eventhandler_register(struct eventhandler_list *list, char *name, /* Do we need to create the list? */ if (list == NULL) { if ((list = malloc(sizeof(struct eventhandler_list) + strlen(name) + 1, - M_EVENTHANDLER, M_NOWAIT)) == NULL) + M_EVENTHANDLER, M_NOWAIT)) == NULL) { + mtx_exit(&eventhandler_mutex, MTX_DEF); return(NULL); + } list->el_flags = 0; list->el_name = (char *)list + sizeof(struct eventhandler_list); strcpy(list->el_name, name); @@ -79,18 +85,22 @@ 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); list->el_flags = EHE_INITTED; } /* allocate an entry for this handler, populate it */ if ((eg = malloc(sizeof(struct eventhandler_entry_generic), - M_EVENTHANDLER, M_NOWAIT)) == NULL) + M_EVENTHANDLER, M_NOWAIT)) == NULL) { + mtx_exit(&eventhandler_mutex, MTX_DEF); return(NULL); + } eg->func = func; eg->ee.ee_arg = arg; eg->ee.ee_priority = priority; /* sort it into the list */ + mtx_enter(&list->el_mutex, MTX_DEF); for (ep = TAILQ_FIRST(&list->el_entries); ep != NULL; ep = TAILQ_NEXT(ep, ee_link)) { @@ -101,6 +111,8 @@ 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); + mtx_exit(&eventhandler_mutex, MTX_DEF); return(&eg->ee); } @@ -110,6 +122,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); if (ep != NULL) { /* remove just this entry */ TAILQ_REMOVE(&list->el_entries, ep, ee_link); @@ -122,19 +135,24 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag) free(ep, M_EVENTHANDLER); } } + mtx_exit(&list->el_mutex, MTX_DEF); } struct eventhandler_list * eventhandler_find_list(char *name) { struct eventhandler_list *list; - + /* scan looking for the requested list */ + mtx_enter(&eventhandler_mutex, MTX_DEF); for (list = TAILQ_FIRST(&eventhandler_lists); list != NULL; list = TAILQ_NEXT(list, el_link)) { if (!strcmp(name, list->el_name)) break; } + mtx_exit(&eventhandler_mutex, MTX_DEF); + return(list); } + diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h index 0d879b7..01777cd 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -27,6 +27,8 @@ */ #include +#include /* XXX should these be prerequisites? */ +#include #ifndef SYS_EVENTHANDLER_H #define SYS_EVENTHANDLER_H @@ -40,14 +42,16 @@ struct eventhandler_entry struct eventhandler_list { - TAILQ_ENTRY(eventhandler_list) el_link; char *el_name; int el_flags; #define EHE_INITTED (1<<0) + struct mtx el_mutex; + TAILQ_ENTRY(eventhandler_list) el_link; TAILQ_HEAD(,eventhandler_entry) el_entries; }; typedef struct eventhandler_entry *eventhandler_tag; +struct mtx eventhandler_mutex; /* * Fast handler lists require the eventhandler list be present @@ -72,29 +76,33 @@ struct __hack struct eventhandler_list Xeventhandler_list_ ## name = { #name }; \ 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)); \ - \ - while (_ep != NULL) { \ - ((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , ## args); \ - _ep = TAILQ_NEXT(_ep, ee_link); \ - } \ +#define EVENTHANDLER_FAST_INVOKE(name, args...) \ +do { \ + struct eventhandler_list *_el = &Xeventhandler_list_ ## name ; \ + struct eventhandler_entry *_ep = TAILQ_FIRST(&(_el->el_entries)); \ + \ + if (_el->el_flags & EHE_INITTED) { \ + mtx_enter(&_el->el_mutex, MTX_DEF); \ + while (_ep != NULL) { \ + ((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , \ + ## args); \ + _ep = TAILQ_NEXT(_ep, ee_link); \ + } \ + mtx_exit(&_el->el_mutex, MTX_DEF); \ + } \ } while (0) #define EVENTHANDLER_FAST_REGISTER(name, func, arg, priority) \ - eventhandler_register(Xeventhandler_list_ ## name, #name, func, arg, priority) + eventhandler_register(&Xeventhandler_list_ ## name, #name, func, arg, priority) #define EVENTHANDLER_FAST_DEREGISTER(name, tag) \ - eventhandler_deregister(Xeventhandler_list ## name, tag) - + eventhandler_deregister(&Xeventhandler_list ## name, tag) /* - * Slow handlerss are entirely dynamic; lists are created + * Slow handlers are entirely dynamic; lists are created * when entries are added to them, and thus have no concept of "owner", * - * Slow handlerss need to be declared, but do not need to be defined. The + * Slow handlers need to be declared, but do not need to be defined. The * declaration must be in scope wherever the handler is to be invoked. */ #define EVENTHANDLER_DECLARE(name, type) \ @@ -105,18 +113,22 @@ struct eventhandler_entry_ ## name \ }; \ struct __hack -#define EVENTHANDLER_INVOKE(name, args...) \ -do { \ - struct eventhandler_list *_el; \ - struct eventhandler_entry *_ep; \ - \ - if ((_el = eventhandler_find_list(#name)) != NULL) { \ - for (_ep = TAILQ_FIRST(&(_el->el_entries)); \ - _ep != NULL; \ - _ep = TAILQ_NEXT(_ep, ee_link)) { \ - ((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , ## args); \ - } \ - } \ +#define EVENTHANDLER_INVOKE(name, args...) \ +do { \ + struct eventhandler_list *_el; \ + struct eventhandler_entry *_ep; \ + \ + if (((_el = eventhandler_find_list(#name)) != NULL) && \ + (_el->el_flags & EHE_INITTED)) { \ + mtx_enter(&_el->el_mutex, MTX_DEF); \ + for (_ep = TAILQ_FIRST(&(_el->el_entries)); \ + _ep != NULL; \ + _ep = TAILQ_NEXT(_ep, ee_link)) { \ + ((struct eventhandler_entry_ ## name *)_ep)->eh_func(_ep->ee_arg , \ + ## args); \ + } \ + mtx_exit(&_el->el_mutex, MTX_DEF); \ + } \ } while (0) #define EVENTHANDLER_REGISTER(name, func, arg, priority) \ @@ -155,4 +167,11 @@ EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); +/* Idle process event */ +typedef void (*idle_eventhandler_t) __P((void *, int)); + +#define IDLE_PRI_LAST 20000 +EVENTHANDLER_FAST_DECLARE(idle_event, idle_eventhandler_t); + + #endif /* SYS_EVENTHANDLER_H */ -- cgit v1.1