Module Name:    src
Committed By:   ozaki-r
Date:           Sun Nov 23 10:00:20 UTC 2014

Modified Files:
        src/sys/dev/sysmon: sysmon_envsys.c sysmon_envsys_events.c
            sysmon_envsysvar.h

Log Message:
Pull workqueue_destroy out of sme->sme_mtx

workqueue_destroy may sleep so we shouldn't run it with holding a mutex.

Requested by riastradh@.


To generate a diff of this commit:
cvs rdiff -u -r1.127 -r1.128 src/sys/dev/sysmon/sysmon_envsys.c
cvs rdiff -u -r1.112 -r1.113 src/sys/dev/sysmon/sysmon_envsys_events.c
cvs rdiff -u -r1.46 -r1.47 src/sys/dev/sysmon/sysmon_envsysvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/sysmon/sysmon_envsys.c
diff -u src/sys/dev/sysmon/sysmon_envsys.c:1.127 src/sys/dev/sysmon/sysmon_envsys.c:1.128
--- src/sys/dev/sysmon/sysmon_envsys.c:1.127	Sun Aug 10 16:44:36 2014
+++ src/sys/dev/sysmon/sysmon_envsys.c	Sun Nov 23 10:00:20 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_envsys.c,v 1.127 2014/08/10 16:44:36 tls Exp $	*/
+/*	$NetBSD: sysmon_envsys.c,v 1.128 2014/11/23 10:00:20 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.127 2014/08/10 16:44:36 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.128 2014/11/23 10:00:20 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -579,6 +579,7 @@ sysmon_envsys_sensor_detach(struct sysmo
 {
 	envsys_data_t *oedata;
 	bool found = false;
+	bool destroy = false;
 
 	KASSERT(sme != NULL || edata != NULL);
 
@@ -604,11 +605,18 @@ sysmon_envsys_sensor_detach(struct sysmo
 	 * remove it, unhook from rnd(4), and decrement the sensors count.
 	 */
 	sme_event_unregister_sensor(sme, edata);
+	if (LIST_EMPTY(&sme->sme_events_list)) {
+		sme_events_halt_callout(sme);
+		destroy = true;
+	}
 	TAILQ_REMOVE(&sme->sme_sensors_list, edata, sensors_head);
 	sme->sme_nsensors--;
 	sysmon_envsys_release(sme, true);
 	mutex_exit(&sme->sme_mtx);
 
+	if (destroy)
+		sme_events_destroy(sme);
+
 	return 0;
 }
 
@@ -918,10 +926,6 @@ sysmon_envsys_unregister(struct sysmon_e
 	KASSERT(sme != NULL);
 
 	/*
-	 * Unregister all events associated with device.
-	 */
-	sme_event_unregister_all(sme);
-	/*
 	 * Decrement global sensors counter and the first_sensor index
 	 * for remaining devices in the list (only used for compatibility
 	 * with previous API), and remove the device from the list.
@@ -936,6 +940,11 @@ sysmon_envsys_unregister(struct sysmon_e
 	mutex_exit(&sme_global_mtx);
 
 	/*
+	 * Unregister all events associated with device.
+	 */
+	sme_event_unregister_all(sme);
+
+	/*
 	 * Remove the device (and all its objects) from the global dictionary.
 	 */
 	array = prop_dictionary_get(sme_propd, sme->sme_name);

Index: src/sys/dev/sysmon/sysmon_envsys_events.c
diff -u src/sys/dev/sysmon/sysmon_envsys_events.c:1.112 src/sys/dev/sysmon/sysmon_envsys_events.c:1.113
--- src/sys/dev/sysmon/sysmon_envsys_events.c:1.112	Sat Nov 22 15:09:30 2014
+++ src/sys/dev/sysmon/sysmon_envsys_events.c	Sun Nov 23 10:00:20 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsys_events.c,v 1.112 2014/11/22 15:09:30 ozaki-r Exp $ */
+/* $NetBSD: sysmon_envsys_events.c,v 1.113 2014/11/23 10:00:20 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.112 2014/11/22 15:09:30 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.113 2014/11/23 10:00:20 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -345,6 +345,7 @@ sme_event_unregister_all(struct sysmon_e
 {
 	sme_event_t *see;
 	int evcounter = 0;
+	bool destroy = false;
 
 	KASSERT(sme != NULL);
 
@@ -374,10 +375,15 @@ sme_event_unregister_all(struct sysmon_e
 		}
 	}
 
-	if (LIST_EMPTY(&sme->sme_events_list))
-		if (sme->sme_flags & SME_CALLOUT_INITIALIZED)
-			sme_events_destroy(sme);
+	if (LIST_EMPTY(&sme->sme_events_list) &&
+	    sme->sme_flags & SME_CALLOUT_INITIALIZED) {
+		sme_events_halt_callout(sme);
+		destroy = true;
+	}
 	mutex_exit(&sme->sme_mtx);
+
+	if (destroy)
+		sme_events_destroy(sme);
 }
 
 /*
@@ -390,6 +396,7 @@ sme_event_unregister(struct sysmon_envsy
 {
 	sme_event_t *see;
 	bool found = false;
+	bool destroy = false;
 
 	KASSERT(sensor != NULL);
 
@@ -420,7 +427,15 @@ sme_event_unregister(struct sysmon_envsy
 
 	sme_remove_event(see, sme);
 
+	if (LIST_EMPTY(&sme->sme_events_list)) {
+		sme_events_halt_callout(sme);
+		destroy = true;
+	}
 	mutex_exit(&sme->sme_mtx);
+
+	if (destroy)
+		sme_events_destroy(sme);
+
 	return 0;
 }
 
@@ -470,15 +485,6 @@ sme_remove_event(sme_event_t *see, struc
 	if (see->see_edata->flags & ENVSYS_FHAS_ENTROPY)
 		rnd_detach_source(&see->see_edata->rnd_src);
 	LIST_REMOVE(see, see_list);
-	/*
-	 * So the events list is empty, we'll do the following:
-	 *
-	 * 	- stop and destroy the callout.
-	 * 	- destroy the workqueue.
-	 */
-	if (LIST_EMPTY(&sme->sme_events_list))
-		sme_events_destroy(sme);
-
 	kmem_free(see, sizeof(*see));
 }
 
@@ -601,13 +607,12 @@ sme_schedule_callout(struct sysmon_envsy
 }
 
 /*
- * sme_events_destroy:
+ * sme_events_halt_callout:
  *
- * 	+ Destroys the event framework for this device: callout
- * 	  stopped, workqueue destroyed and callout mutex destroyed.
+ * 	+ Halt the callout of the event framework for this device.
  */
 void
-sme_events_destroy(struct sysmon_envsys *sme)
+sme_events_halt_callout(struct sysmon_envsys *sme)
 {
 	KASSERT(mutex_owned(&sme->sme_mtx));
 
@@ -618,9 +623,23 @@ sme_events_destroy(struct sysmon_envsys 
 	sme->sme_flags &= ~SME_CALLOUT_INITIALIZED;
 
 	callout_halt(&sme->sme_callout, &sme->sme_mtx);
-	callout_destroy(&sme->sme_callout);
+}
 
+/*
+ * sme_events_destroy:
+ *
+ * 	+ Destroy the callout and the workqueue of the event framework
+ *	  for this device.
+ */
+void
+sme_events_destroy(struct sysmon_envsys *sme)
+{
+	KASSERT(!mutex_owned(&sme->sme_mtx));
+	KASSERT((sme->sme_flags & SME_CALLOUT_INITIALIZED) == 0);
+
+	callout_destroy(&sme->sme_callout);
 	workqueue_destroy(sme->sme_wq);
+
 	DPRINTF(("%s: events framework destroyed for '%s'\n",
 	    __func__, sme->sme_name));
 }

Index: src/sys/dev/sysmon/sysmon_envsysvar.h
diff -u src/sys/dev/sysmon/sysmon_envsysvar.h:1.46 src/sys/dev/sysmon/sysmon_envsysvar.h:1.47
--- src/sys/dev/sysmon/sysmon_envsysvar.h:1.46	Fri Dec 14 03:31:10 2012
+++ src/sys/dev/sysmon/sysmon_envsysvar.h	Sun Nov 23 10:00:20 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsysvar.h,v 1.46 2012/12/14 03:31:10 pgoyette Exp $ */
+/* $NetBSD: sysmon_envsysvar.h,v 1.47 2014/11/23 10:00:20 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -137,6 +137,7 @@ void	sme_event_unregister_all(struct sys
 void	sme_event_drvadd(void *);
 int	sme_events_init(struct sysmon_envsys *);
 void	sme_events_destroy(struct sysmon_envsys *);
+void	sme_events_halt_callout(struct sysmon_envsys *);
 void	sme_events_check(void *);
 void	sme_events_worker(struct work *, void *);
 void	sme_deliver_event(sme_event_t *);

Reply via email to