Index: sys/dev/sysmon/sysmon_envsys.c =================================================================== RCS file: /cvsroot/src/sys/dev/sysmon/sysmon_envsys.c,v retrieving revision 1.143 diff -p -u -r1.143 sysmon_envsys.c --- sys/dev/sysmon/sysmon_envsys.c 26 May 2018 21:15:46 -0000 1.143 +++ sys/dev/sysmon/sysmon_envsys.c 26 Nov 2018 23:17:24 -0000 @@ -84,12 +84,17 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_envsy #include #include -kmutex_t sme_global_mtx; +static kmutex_t sme_global_mtx; +static kcondvar_t sme_global_cv; +static bool sme_global_busy; prop_dictionary_t sme_propd; struct sysmon_envsys_lh sysmon_envsys_list; +static int sysmon_envsys_lock(bool); +static void sysmon_envsys_unlock(void); + static uint32_t sysmon_envsys_next_sensor_index; static struct sysmon_envsys *sysmon_envsys_find_40(u_int); @@ -118,6 +123,7 @@ sme_preinit(void) LIST_INIT(&sysmon_envsys_list); mutex_init(&sme_global_mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&sme_global_cv, "smeglobal"); sme_propd = prop_dictionary_create(); return 0; @@ -150,14 +156,45 @@ sysmon_envsys_fini(void) else error = sysmon_attach_minor(SYSMON_MINOR_ENVSYS, NULL); - if (error == 0) + if (error == 0) { + cv_destroy(&sme_global_cv); mutex_destroy(&sme_global_mtx); + } // XXX: prop_dictionary ??? return error; } +static int +sysmon_envsys_lock(bool sig) +{ + int error = 0; + + mutex_enter(&sme_global_mtx); + while (sme_global_busy && !error) { + if (sig) + error = cv_wait_sig(&sme_global_cv, &sme_global_mtx); + else + cv_wait(&sme_global_cv, &sme_global_mtx); + } + if (!error) + sme_global_busy = true; + mutex_exit(&sme_global_mtx); + + return error; +} + +static void +sysmon_envsys_unlock(void) +{ + + mutex_enter(&sme_global_mtx); + sme_global_busy = false; + cv_signal(&sme_global_cv); + mutex_exit(&sme_global_mtx); +} + /* * sysmonopen_envsys: * @@ -204,7 +241,8 @@ sysmonioctl_envsys(dev_t dev, u_long cmd * Update dictionaries on all sysmon envsys devices * registered. */ - mutex_enter(&sme_global_mtx); + if ((error = sysmon_envsys_lock(true)) != 0) + break; LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { sysmon_envsys_acquire(sme, false); error = sme_update_dictionary(sme); @@ -212,12 +250,12 @@ sysmonioctl_envsys(dev_t dev, u_long cmd DPRINTF(("%s: sme_update_dictionary, " "error=%d\n", __func__, error)); sysmon_envsys_release(sme, false); - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); return error; } sysmon_envsys_release(sme, false); } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); /* * Copy global dictionary to userland. */ @@ -402,9 +440,9 @@ sysmonioctl_envsys(dev_t dev, u_long cmd if (tred->sensor < sme->sme_nsensors) { if ((sme->sme_flags & SME_POLL_ONLY) == 0) { - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); sysmon_envsys_refresh_sensor(sme, edata); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); } /* @@ -531,7 +569,6 @@ sysmon_envsys_create(void) TAILQ_INIT(&sme->sme_sensors_list); LIST_INIT(&sme->sme_events_list); mutex_init(&sme->sme_mtx, MUTEX_DEFAULT, IPL_NONE); - mutex_init(&sme->sme_work_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sme->sme_condvar, "sme_wait"); return sme; @@ -555,7 +592,6 @@ sysmon_envsys_destroy(struct sysmon_envs TAILQ_REMOVE(&sme->sme_sensors_list, edata, sensors_head); } mutex_destroy(&sme->sme_mtx); - mutex_destroy(&sme->sme_work_mtx); cv_destroy(&sme->sme_condvar); kmem_free(sme, sizeof(*sme)); } @@ -587,12 +623,10 @@ sysmon_envsys_sensor_attach(struct sysmo if (strlen(edata->desc) == 0) return EINVAL; - mutex_enter(&sme->sme_mtx); - sysmon_envsys_acquire(sme, true); + sysmon_envsys_acquire(sme, false); TAILQ_FOREACH(oedata, &sme->sme_sensors_list, sensors_head) { if (strcmp(oedata->desc, edata->desc) == 0) { - sysmon_envsys_release(sme, true); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); return EEXIST; } } @@ -606,8 +640,7 @@ sysmon_envsys_sensor_attach(struct sysmo */ edata->sensor = sme->sme_nsensors; sme->sme_nsensors++; - sysmon_envsys_release(sme, true); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); DPRINTF(("%s: attached #%d (%s), units=%d (%s)\n", __func__, edata->sensor, edata->desc, @@ -634,8 +667,7 @@ sysmon_envsys_sensor_detach(struct sysmo /* * Check the sensor is already on the list. */ - mutex_enter(&sme->sme_mtx); - sysmon_envsys_acquire(sme, true); + sysmon_envsys_acquire(sme, false); TAILQ_FOREACH(oedata, &sme->sme_sensors_list, sensors_head) { if (oedata->sensor == edata->sensor) { found = true; @@ -644,8 +676,7 @@ sysmon_envsys_sensor_detach(struct sysmo } if (!found) { - sysmon_envsys_release(sme, true); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); return EINVAL; } @@ -662,8 +693,7 @@ sysmon_envsys_sensor_detach(struct sysmo } TAILQ_REMOVE(&sme->sme_sensors_list, edata, sensors_head); sme->sme_nsensors--; - sysmon_envsys_release(sme, true); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); if (destroy) sme_events_destroy(sme); @@ -705,14 +735,15 @@ sysmon_envsys_register(struct sysmon_env * Check if requested sysmon_envsys device is valid * and does not exist already in the list. */ - mutex_enter(&sme_global_mtx); + if ((error = sysmon_envsys_lock(true)) != 0) + return error; LIST_FOREACH(lsme, &sysmon_envsys_list, sme_list) { if (strcmp(lsme->sme_name, sme->sme_name) == 0) { - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); return EEXIST; } } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); /* * sanity check: if SME_DISABLE_REFRESH is not set, @@ -797,10 +828,13 @@ sysmon_envsys_register(struct sysmon_env * * ... */ - mutex_enter(&sme_global_mtx); + if ((error = sysmon_envsys_lock(true)) != 0) { + DPRINTF(("%s: global dictionary lock aborted\n", __func__)); + goto out; + } if (!prop_dictionary_set(sme_propd, sme->sme_name, array)) { error = EINVAL; - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); DPRINTF(("%s: prop_dictionary_set for '%s'\n", __func__, sme->sme_name)); goto out; @@ -812,7 +846,7 @@ sysmon_envsys_register(struct sysmon_env LIST_INSERT_HEAD(&sysmon_envsys_list, sme, sme_list); sme->sme_fsensor = sysmon_envsys_next_sensor_index; sysmon_envsys_next_sensor_index += sme->sme_nsensors; - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); out: /* @@ -984,14 +1018,14 @@ sysmon_envsys_unregister(struct sysmon_e * for remaining devices in the list (only used for compatibility * with previous API), and remove the device from the list. */ - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); sysmon_envsys_next_sensor_index -= sme->sme_nsensors; LIST_FOREACH(osme, &sysmon_envsys_list, sme_list) { if (osme->sme_fsensor >= sme->sme_fsensor) osme->sme_fsensor -= sme->sme_nsensors; } LIST_REMOVE(sme, sme_list); - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); TAILQ_FOREACH(edata, &sme->sme_sensors_list, sensors_head) { sysmon_envsys_sensor_detach(sme, edata); @@ -1007,9 +1041,9 @@ sysmon_envsys_unregister(struct sysmon_e */ array = prop_dictionary_get(sme_propd, sme->sme_name); if (array && prop_object_type(array) == PROP_TYPE_ARRAY) { - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); prop_dictionary_remove(sme_propd, sme->sme_name); - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); sysmon_envsys_destroy_plist(array); } /* @@ -1029,14 +1063,14 @@ sysmon_envsys_find(const char *name) { struct sysmon_envsys *sme; - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { if (strcmp(sme->sme_name, name) == 0) { sysmon_envsys_acquire(sme, false); break; } } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); return sme; } @@ -1049,7 +1083,7 @@ sysmon_envsys_find_40(u_int idx) { struct sysmon_envsys *sme; - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { if (idx >= sme->sme_fsensor && idx < (sme->sme_fsensor + sme->sme_nsensors)) { @@ -1057,7 +1091,7 @@ sysmon_envsys_find_40(u_int idx) break; } } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); return sme; } @@ -1074,6 +1108,7 @@ sysmon_envsys_acquire(struct sysmon_envs KASSERT(sme != NULL); if (locked) { + KASSERT(mutex_owned(&sme->sme_mtx)); while (sme->sme_flags & SME_FLAG_BUSY) cv_wait(&sme->sme_condvar, &sme->sme_mtx); sme->sme_flags |= SME_FLAG_BUSY; @@ -1098,6 +1133,7 @@ sysmon_envsys_release(struct sysmon_envs KASSERT(sme != NULL); if (locked) { + KASSERT(mutex_owned(&sme->sme_mtx)); sme->sme_flags &= ~SME_FLAG_BUSY; cv_broadcast(&sme->sme_condvar); } else { @@ -1121,12 +1157,10 @@ sme_initial_refresh(void *arg) struct sysmon_envsys *sme = arg; envsys_data_t *edata; - mutex_enter(&sme->sme_mtx); - sysmon_envsys_acquire(sme, true); + sysmon_envsys_acquire(sme, false); TAILQ_FOREACH(edata, &sme->sme_sensors_list, sensors_head) sysmon_envsys_refresh_sensor(sme, edata); - sysmon_envsys_release(sme, true); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); } /* @@ -1178,7 +1212,7 @@ sme_remove_userprops(void) uint32_t props; int ptype; - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { sysmon_envsys_acquire(sme, false); array = prop_dictionary_get(sme_propd, sme->sme_name); @@ -1336,7 +1370,7 @@ sme_remove_userprops(void) sysmon_envsys_release(sme, true); mutex_exit(&sme->sme_mtx); } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); } /* @@ -1550,7 +1584,7 @@ sysmon_envsys_get_max_value(bool (*predi uint32_t maxv, v; maxv = 0; - mutex_enter(&sme_global_mtx); + sysmon_envsys_lock(false); LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { sysmon_envsys_acquire(sme, false); v = sme_get_max_value(sme, predicate, refresh); @@ -1558,7 +1592,7 @@ sysmon_envsys_get_max_value(bool (*predi if (v > maxv) maxv = v; } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); return maxv; } @@ -1581,9 +1615,9 @@ sme_get_max_value(struct sysmon_envsys * /* * refresh sensor data */ - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); sysmon_envsys_refresh_sensor(sme, edata); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); v = edata->value_cur; if (v > maxv) @@ -1655,9 +1689,7 @@ sme_update_dictionary(struct sysmon_envs /* * refresh sensor data via sme_envsys_refresh_sensor */ - mutex_enter(&sme->sme_mtx); sysmon_envsys_refresh_sensor(sme, edata); - mutex_exit(&sme->sme_mtx); /* * retrieve sensor's dictionary. @@ -1923,19 +1955,17 @@ sme_userset_dictionary(struct sysmon_env /* * Update the object in dictionary. */ - mutex_enter(&sme->sme_mtx); error = sme_sensor_upstring(dict, "description", blah); if (error) { - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); goto out; } DPRINTF(("%s: sensor%d changed desc to: %s\n", __func__, edata->sensor, blah)); edata->upropset |= PROP_DESC; - mutex_exit(&sme->sme_mtx); } /* @@ -1945,10 +1975,8 @@ sme_userset_dictionary(struct sysmon_env if (obj2 && prop_object_type(obj2) == PROP_TYPE_NUMBER) { targetfound = true; if (edata->flags & ENVSYS_FCHANGERFACT) { - mutex_enter(&sme->sme_mtx); edata->rfact = prop_number_integer_value(obj2); edata->upropset |= PROP_RFACT; - mutex_exit(&sme->sme_mtx); DPRINTF(("%s: sensor%d changed rfact to %d\n", __func__, edata->sensor, edata->rfact)); } else { @@ -2086,22 +2114,23 @@ sysmon_envsys_foreach_sensor(sysmon_envs struct sysmon_envsys *sme; envsys_data_t *sensor; - mutex_enter(&sme_global_mtx); + if (sysmon_envsys_lock(true)) + return; LIST_FOREACH(sme, &sysmon_envsys_list, sme_list) { sysmon_envsys_acquire(sme, false); TAILQ_FOREACH(sensor, &sme->sme_sensors_list, sensors_head) { if (refresh) { - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); sysmon_envsys_refresh_sensor(sme, sensor); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); } if (!(*func)(sme, sensor, arg)) break; } sysmon_envsys_release(sme, false); } - mutex_exit(&sme_global_mtx); + sysmon_envsys_unlock(); } /* Index: sys/dev/sysmon/sysmon_envsys_events.c =================================================================== RCS file: /cvsroot/src/sys/dev/sysmon/sysmon_envsys_events.c,v retrieving revision 1.121 diff -p -u -r1.121 sysmon_envsys_events.c --- sys/dev/sysmon/sysmon_envsys_events.c 11 Sep 2017 06:02:09 -0000 1.121 +++ sys/dev/sysmon/sysmon_envsys_events.c 26 Nov 2018 23:17:24 -0000 @@ -169,7 +169,7 @@ sme_event_register(prop_dictionary_t sdi * check if the event is already on the list and return * EEXIST if value provided hasn't been changed. */ - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); LIST_FOREACH(osee, &sme->sme_events_list, see_list) { if (strcmp(edata->desc, osee->see_pes.pes_sensname) != 0) continue; @@ -221,7 +221,7 @@ sme_event_register(prop_dictionary_t sdi break; } if (crittype == PENVSYS_EVENT_NULL && see != NULL) { - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); return EEXIST; } @@ -328,7 +328,7 @@ out: if ((error == 0 || error == EEXIST) && osee == NULL) LIST_INSERT_HEAD(&sme->sme_events_list, see, see_list); - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); return error; } @@ -561,7 +561,6 @@ sme_events_init(struct sysmon_envsys *sm int error = 0; KASSERT(sme != NULL); - KASSERT(mutex_owned(&sme->sme_mtx)); error = workqueue_create(&sme->sme_wq, sme->sme_name, sme_events_worker, sme, PRI_NONE, IPL_SOFTCLOCK, WQ_MPSAFE); @@ -571,7 +570,9 @@ sme_events_init(struct sysmon_envsys *sm callout_init(&sme->sme_callout, CALLOUT_MPSAFE); callout_setfunc(&sme->sme_callout, sme_events_check, sme); sme->sme_callout_state = SME_CALLOUT_READY; + mutex_enter(&sme->sme_mtx); sme_schedule_callout(sme); + mutex_exit(&sme->sme_mtx); DPRINTF(("%s: events framework initialized for '%s'\n", __func__, sme->sme_name)); @@ -736,14 +737,13 @@ sme_events_check(void *arg) KASSERT(sme != NULL); - mutex_enter(&sme->sme_work_mtx); + mutex_enter(&sme->sme_mtx); if (sme->sme_busy > 0) { log(LOG_WARNING, "%s: workqueue busy: updates stopped\n", sme->sme_name); - mutex_exit(&sme->sme_work_mtx); + mutex_exit(&sme->sme_mtx); return; } - mutex_enter(&sme->sme_mtx); LIST_FOREACH(see, &sme->sme_events_list, see_list) { workqueue_enqueue(sme->sme_wq, &see->see_wk, NULL); see->see_edata->flags |= ENVSYS_FNEED_REFRESH; @@ -752,7 +752,6 @@ sme_events_check(void *arg) if (!sysmon_low_power) sme_schedule_callout(sme); mutex_exit(&sme->sme_mtx); - mutex_exit(&sme->sme_work_mtx); } /* @@ -772,7 +771,7 @@ sme_events_worker(struct work *wk, void KASSERT(sme != NULL); KASSERT(edata != NULL); - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); see->see_flags |= SEE_EVENT_WORKING; /* * sme_events_check marks the sensors to make us refresh them here. @@ -829,11 +828,10 @@ sme_events_worker(struct work *wk, void out: see->see_flags &= ~SEE_EVENT_WORKING; - cv_broadcast(&sme->sme_condvar); - mutex_enter(&sme->sme_work_mtx); + mutex_enter(&sme->sme_mtx); KASSERT(sme->sme_busy > 0); sme->sme_busy--; - mutex_exit(&sme->sme_work_mtx); + sysmon_envsys_release(sme, true); mutex_exit(&sme->sme_mtx); } @@ -850,7 +848,7 @@ sysmon_envsys_sensor_event(struct sysmon { sme_event_t *see; - mutex_enter(&sme->sme_mtx); + sysmon_envsys_acquire(sme, false); LIST_FOREACH(see, &sme->sme_events_list, see_list) { if (edata != see->see_edata) continue; @@ -861,7 +859,7 @@ sysmon_envsys_sensor_event(struct sysmon break; } } - mutex_exit(&sme->sme_mtx); + sysmon_envsys_release(sme, false); } /* Index: sys/dev/sysmon/sysmon_envsysvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/sysmon/sysmon_envsysvar.h,v retrieving revision 1.47 diff -p -u -r1.47 sysmon_envsysvar.h --- sys/dev/sysmon/sysmon_envsysvar.h 23 Nov 2014 10:00:20 -0000 1.47 +++ sys/dev/sysmon/sysmon_envsysvar.h 26 Nov 2018 23:17:24 -0000 @@ -101,10 +101,9 @@ struct sme_descr_entry { const char *desc; }; -/* +/* * common stuff. */ -extern kmutex_t sme_global_mtx; /* for the sme linked list and dict */ extern prop_dictionary_t sme_propd; /* the global sensor dictionary */ /* Index: sys/dev/sysmon/sysmonvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/sysmon/sysmonvar.h,v retrieving revision 1.50 diff -p -u -r1.50 sysmonvar.h --- sys/dev/sysmon/sysmonvar.h 11 Sep 2017 06:02:09 -0000 1.50 +++ sys/dev/sysmon/sysmonvar.h 26 Nov 2018 23:17:24 -0000 @@ -212,11 +212,8 @@ struct sysmon_envsys { /* * Locking/synchronization. */ - int sme_busy; /* number of items on workqueue, - sme_mtx or sme_work_mtx to read, - both to write */ + int sme_busy; /* number of items on workqueue */ kmutex_t sme_mtx; - kmutex_t sme_work_mtx; kcondvar_t sme_condvar; };