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