commit e98effc7019769cda1b223e50a735b8b8f84e8c1 Author: Ryota Ozaki Date: Mon Nov 17 17:33:43 2014 +0900 Pull workqueue_destroy out of sme->sme_mtx diff --git a/sys/dev/sysmon/sysmon_envsys.c b/sys/dev/sysmon/sysmon_envsys.c index 57967ea..2832ce7 100644 --- a/sys/dev/sysmon/sysmon_envsys.c +++ b/sys/dev/sysmon/sysmon_envsys.c @@ -579,6 +579,7 @@ sysmon_envsys_sensor_detach(struct sysmon_envsys *sme, envsys_data_t *edata) { envsys_data_t *oedata; bool found = false; + bool destroy = false; KASSERT(sme != NULL || edata != NULL); @@ -604,11 +605,18 @@ sysmon_envsys_sensor_detach(struct sysmon_envsys *sme, envsys_data_t *edata) * 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_envsys *sme) 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_envsys *sme) 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); diff --git a/sys/dev/sysmon/sysmon_envsys_events.c b/sys/dev/sysmon/sysmon_envsys_events.c index 38c5914..56409fa 100644 --- a/sys/dev/sysmon/sysmon_envsys_events.c +++ b/sys/dev/sysmon/sysmon_envsys_events.c @@ -345,6 +345,7 @@ sme_event_unregister_all(struct sysmon_envsys *sme) { sme_event_t *see; int evcounter = 0; + bool destroy = false; KASSERT(sme != NULL); @@ -374,10 +375,15 @@ sme_event_unregister_all(struct sysmon_envsys *sme) } } - 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); } /* @@ -470,15 +476,6 @@ sme_remove_event(sme_event_t *see, struct sysmon_envsys *sme) 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 +598,12 @@ sme_schedule_callout(struct sysmon_envsys *sme) } /* - * 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 +614,23 @@ sme_events_destroy(struct sysmon_envsys *sme) sme->sme_flags &= ~SME_CALLOUT_INITIALIZED; callout_halt(&sme->sme_callout, &sme->sme_mtx); +} + +/* + * 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)); } diff --git a/sys/dev/sysmon/sysmon_envsysvar.h b/sys/dev/sysmon/sysmon_envsysvar.h index 52128f4..84b76d4 100644 --- a/sys/dev/sysmon/sysmon_envsysvar.h +++ b/sys/dev/sysmon/sysmon_envsysvar.h @@ -137,6 +137,7 @@ void sme_event_unregister_all(struct sysmon_envsys *); 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 *);