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 *);