From a4bf8740bb46d337eb18ae335c2f3b023098c63d Mon Sep 17 00:00:00 2001
From: msmith <msmith@FreeBSD.org>
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 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

(limited to 'sys/kern/subr_eventhandler.c')

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);
 }
+
-- 
cgit v1.1