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 <dev/sysmon/sysmon_envsysvar.h>
#include <dev/sysmon/sysmon_taskq.h>
-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
* <array>
* ...
*/
- 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;
};