Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sysmon Improve tracking of the state of an event's c...
details: https://anonhg.NetBSD.org/src/rev/d21f1c838c3c
branches: trunk
changeset: 826536:d21f1c838c3c
user: pgoyette <pgoyette%NetBSD.org@localhost>
date: Mon Sep 11 06:02:09 2017 +0000
description:
Improve tracking of the state of an event's callout, and protect all
queries or modifications of the state with the sme_mtx mutex.
Detach the rndsrc before re-attaching it (with potentially new values).
Clean up some lock-ordering issues.
And a couple of KNF issues for good measure!
Should address PR kern/52533
XXX Pullup-8 along with the previous fixes from msaitoh@
XXX http://mail-index.netbsd.org/source-changes/2017/09/06/msg088028.html
~
~
diffstat:
sys/dev/sysmon/sysmon_envsys.c | 45 +++++++++++++++++++++++++------
sys/dev/sysmon/sysmon_envsys_events.c | 49 ++++++++++++++++++++---------------
sys/dev/sysmon/sysmonvar.h | 9 +++++-
3 files changed, 71 insertions(+), 32 deletions(-)
diffs (285 lines):
diff -r d6897caa1b90 -r d21f1c838c3c sys/dev/sysmon/sysmon_envsys.c
--- a/sys/dev/sysmon/sysmon_envsys.c Mon Sep 11 05:25:53 2017 +0000
+++ b/sys/dev/sysmon/sysmon_envsys.c Mon Sep 11 06:02:09 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsys.c,v 1.140 2017/09/06 11:08:53 msaitoh Exp $ */
+/* $NetBSD: sysmon_envsys.c,v 1.141 2017/09/11 06:02:09 pgoyette 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.140 2017/09/06 11:08:53 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.141 2017/09/11 06:02:09 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -525,6 +525,8 @@
{
struct sysmon_envsys *sme;
+ CTASSERT(SME_CALLOUT_INVALID == 0);
+
sme = kmem_zalloc(sizeof(*sme), KM_SLEEP);
TAILQ_INIT(&sme->sme_sensors_list);
LIST_INIT(&sme->sme_events_list);
@@ -654,7 +656,8 @@
rnd_detach_source(&oedata->rnd_src);
sme_event_unregister_sensor(sme, edata);
if (LIST_EMPTY(&sme->sme_events_list)) {
- sme_events_halt_callout(sme);
+ if (sme->sme_callout_state == SME_CALLOUT_READY)
+ sme_events_halt_callout(sme);
destroy = true;
}
TAILQ_REMOVE(&sme->sme_sensors_list, edata, sensors_head);
@@ -1269,15 +1272,23 @@
}
/*
- * Finally, remove any old limits event, then
- * install a new event (which will update the
- * dictionary)
+ * If the sensor is providing entropy data,
+ * get rid of the rndsrc; we'll provide a new
+ * one shortly.
+ */
+ if (edata->flags & ENVSYS_FHAS_ENTROPY)
+ rnd_detach_source(&edata->rnd_src);
+
+ /*
+ * Remove the old limits event, if any
*/
sme_event_unregister(sme, edata->desc,
PENVSYS_EVENT_LIMITS);
/*
- * Find the correct units for this sensor.
+ * Create and install a new event (which will
+ * update the dictionary) with the correct
+ * units.
*/
sdt_units = sme_find_table_entry(SME_DESC_UNITS,
edata->units);
@@ -1290,6 +1301,11 @@
&lims, props, PENVSYS_EVENT_LIMITS,
sdt_units->crittype);
}
+
+ /* Finally, if the sensor provides entropy,
+ * create an additional event entry and attach
+ * the rndsrc
+ */
if (edata->flags & ENVSYS_FHAS_ENTROPY) {
sme_event_register(sdict, edata, sme,
&lims, props, PENVSYS_EVENT_NULL,
@@ -1308,8 +1324,17 @@
* Restore default timeout value.
*/
sme->sme_events_timeout = SME_EVENTS_DEFTIMEOUT;
+
+ /*
+ * Note that we need to hold the sme_mtx while calling
+ * sme_schedule_callout(). Thus to avoid dropping,
+ * reacquiring, and dropping it again, we just tell
+ * sme_envsys_release() that the mutex is already owned.
+ */
+ mutex_enter(&sme->sme_mtx);
sme_schedule_callout(sme);
- sysmon_envsys_release(sme, false);
+ sysmon_envsys_release(sme, true);
+ mutex_exit(&sme->sme_mtx);
}
mutex_exit(&sme_global_mtx);
}
@@ -1350,7 +1375,9 @@
*/
if (sme->sme_events_timeout == 0) {
sme->sme_events_timeout = SME_EVENTS_DEFTIMEOUT;
+ mutex_enter(&sme->sme_mtx);
sme_schedule_callout(sme);
+ mutex_exit(&sme->sme_mtx);
}
if (!prop_dictionary_set_uint64(pdict, "refresh-timeout",
@@ -1824,7 +1851,7 @@
sme_schedule_callout(sme);
}
mutex_exit(&sme->sme_mtx);
- }
+ }
}
return error;
diff -r d6897caa1b90 -r d21f1c838c3c sys/dev/sysmon/sysmon_envsys_events.c
--- a/sys/dev/sysmon/sysmon_envsys_events.c Mon Sep 11 05:25:53 2017 +0000
+++ b/sys/dev/sysmon/sysmon_envsys_events.c Mon Sep 11 06:02:09 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsys_events.c,v 1.120 2017/09/06 11:08:53 msaitoh Exp $ */
+/* $NetBSD: sysmon_envsys_events.c,v 1.121 2017/09/11 06:02:09 pgoyette 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.120 2017/09/06 11:08:53 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.121 2017/09/11 06:02:09 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -313,7 +313,7 @@
/*
* Initialize the events framework if it wasn't initialized before.
*/
- if ((sme->sme_flags & SME_CALLOUT_INITIALIZED) == 0)
+ if (sme->sme_callout_state == SME_CALLOUT_INVALID)
error = sme_events_init(sme);
/*
@@ -374,7 +374,7 @@
}
if (LIST_EMPTY(&sme->sme_events_list) &&
- sme->sme_flags & SME_CALLOUT_INITIALIZED) {
+ sme->sme_callout_state == SME_CALLOUT_READY) {
sme_events_halt_callout(sme);
destroy = true;
}
@@ -570,7 +570,7 @@
callout_init(&sme->sme_callout, CALLOUT_MPSAFE);
callout_setfunc(&sme->sme_callout, sme_events_check, sme);
- sme->sme_flags |= SME_CALLOUT_INITIALIZED;
+ sme->sme_callout_state = SME_CALLOUT_READY;
sme_schedule_callout(sme);
DPRINTF(("%s: events framework initialized for '%s'\n",
__func__, sme->sme_name));
@@ -589,8 +589,9 @@
uint64_t timo;
KASSERT(sme != NULL);
+ KASSERT(mutex_owned(&sme->sme_mtx));
- if ((sme->sme_flags & SME_CALLOUT_INITIALIZED) == 0)
+ if (sme->sme_callout_state != SME_CALLOUT_READY)
return;
if (sme->sme_events_timeout)
@@ -610,14 +611,18 @@
void
sme_events_halt_callout(struct sysmon_envsys *sme)
{
+
KASSERT(mutex_owned(&sme->sme_mtx));
+ KASSERT(sme->sme_callout_state == SME_CALLOUT_READY);
/*
- * Unset before callout_halt to ensure callout is not scheduled again
- * during callout_halt.
+ * Set HALTED before callout_halt to ensure callout is not
+ * scheduled again during callout_halt. (callout_halt()
+ * can potentially release the mutex, so an active callout
+ * could reschedule itself if it grabs the mutex.)
*/
- sme->sme_flags &= ~SME_CALLOUT_INITIALIZED;
+ sme->sme_callout_state = SME_CALLOUT_HALTED;
callout_halt(&sme->sme_callout, &sme->sme_mtx);
}
@@ -630,11 +635,15 @@
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);
+ if (sme->sme_callout_state == SME_CALLOUT_HALTED) {
+ callout_destroy(&sme->sme_callout);
+ sme->sme_callout_state = SME_CALLOUT_INVALID;
+ workqueue_destroy(sme->sme_wq);
+ }
+ KASSERT(sme->sme_callout_state == SME_CALLOUT_INVALID);
DPRINTF(("%s: events framework destroyed for '%s'\n",
__func__, sme->sme_name));
@@ -734,13 +743,7 @@
mutex_exit(&sme->sme_work_mtx);
return;
}
- if (!mutex_tryenter(&sme->sme_mtx)) {
- /* can't get lock - try again later */
- if (!sysmon_low_power)
- sme_schedule_callout(sme);
- mutex_exit(&sme->sme_work_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;
@@ -748,8 +751,8 @@
}
if (!sysmon_low_power)
sme_schedule_callout(sme);
+ mutex_exit(&sme->sme_mtx);
mutex_exit(&sme->sme_work_mtx);
- mutex_exit(&sme->sme_mtx);
}
/*
@@ -1003,12 +1006,16 @@
*/
if (!sysmon_low_power && sme_event_check_low_power()) {
struct penvsys_state pes;
+ struct sysmon_envsys *sme = see->see_sme;
/*
* Stop the callout and send the 'low-power' event.
*/
sysmon_low_power = true;
- callout_stop(&see->see_sme->sme_callout);
+ KASSERT(mutex_owned(&sme->sme_mtx));
+ KASSERT(sme->sme_callout_state == SME_CALLOUT_READY);
+ callout_stop(&sme->sme_callout);
+ sme->sme_callout_state = SME_CALLOUT_HALTED;
pes.pes_type = PENVSYS_TYPE_BATTERY;
sysmon_penvsys_event(&pes, PENVSYS_EVENT_LOW_POWER);
}
diff -r d6897caa1b90 -r d21f1c838c3c sys/dev/sysmon/sysmonvar.h
--- a/sys/dev/sysmon/sysmonvar.h Mon Sep 11 05:25:53 2017 +0000
+++ b/sys/dev/sysmon/sysmonvar.h Mon Sep 11 06:02:09 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmonvar.h,v 1.49 2015/04/23 23:22:03 pgoyette Exp $ */
+/* $NetBSD: sysmonvar.h,v 1.50 2017/09/11 06:02:09 pgoyette Exp $ */
/*-
* Copyright (c) 2000 Zembu Labs, Inc.
@@ -163,7 +163,6 @@
int sme_flags; /* additional flags */
#define SME_FLAG_BUSY 0x00000001 /* device busy */
#define SME_DISABLE_REFRESH 0x00000002 /* disable sme_refresh */
-#define SME_CALLOUT_INITIALIZED 0x00000004 /* callout was initialized */
#define SME_INIT_REFRESH 0x00000008 /* call sme_refresh() after
interrupts are enabled in
the autoconf(9) process. */
@@ -187,6 +186,12 @@
struct workqueue *sme_wq; /* the workqueue for the events */
struct callout sme_callout; /* for the events */
+ int sme_callout_state; /* state of the event's callout */
+
+#define SME_CALLOUT_INVALID 0x0 /* callout is not initialized */
+#define SME_CALLOUT_READY 0x1 /* callout is ready for use */
+#define SME_CALLOUT_HALTED 0x2 /* callout can be destroyed */
+
uint64_t sme_events_timeout; /* the timeout used in the callout */
/*
Home |
Main Index |
Thread Index |
Old Index