summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2013-11-04 00:25:14 +0000
committerdlg <dlg@openbsd.org>2013-11-04 00:25:14 +0000
commitb3316ca552a809646a88f890c5207abe7eb30601 (patch)
tree705c0ca3b592f9b32143f8885a3e43e2767ab6ea /sys
parentSimplify jme_miibus_readreg() / jme_miibus_writereg() a bit by using the (diff)
downloadwireguard-openbsd-b3316ca552a809646a88f890c5207abe7eb30601.tar.xz
wireguard-openbsd-b3316ca552a809646a88f890c5207abe7eb30601.zip
move kernel sensor tasks from using workqs to tasks. while here
whack the locking and task cancellation. sensor updates tested locally, and by mpi@ on ugold(4). ok mpi@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_sensors.c85
1 files changed, 34 insertions, 51 deletions
diff --git a/sys/kern/kern_sensors.c b/sys/kern/kern_sensors.c
index 69ef0513b26..efbef3ae3d7 100644
--- a/sys/kern/kern_sensors.c
+++ b/sys/kern/kern_sensors.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sensors.c,v 1.25 2013/03/28 16:58:45 deraadt Exp $ */
+/* $OpenBSD: kern_sensors.c,v 1.26 2013/11/04 00:25:14 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -26,7 +26,8 @@
#include <sys/device.h>
#include <sys/hotplug.h>
#include <sys/timeout.h>
-#include <sys/workq.h>
+#include <sys/task.h>
+#include <sys/rwlock.h>
#include <sys/sensors.h>
#include "hotplug.h"
@@ -172,25 +173,25 @@ struct sensor_task {
void (*func)(void *);
void *arg;
- int period;
+ unsigned int period;
struct timeout timeout;
- volatile enum {
- ST_TICKING,
- ST_WORKQ,
- ST_RUNNING,
- ST_DYING,
- ST_DEAD
- } state;
+ struct task task;
+ struct rwlock lock;
};
void sensor_task_tick(void *);
void sensor_task_work(void *, void *);
struct sensor_task *
-sensor_task_register(void *arg, void (*func)(void *), int period)
+sensor_task_register(void *arg, void (*func)(void *), unsigned int period)
{
struct sensor_task *st;
+#ifdef DIAGNOSTIC
+ if (period == 0)
+ panic("sensor_task_register: period is 0");
+#endif
+
st = malloc(sizeof(struct sensor_task), M_DEVBUF, M_NOWAIT);
if (st == NULL)
return (NULL);
@@ -199,6 +200,8 @@ sensor_task_register(void *arg, void (*func)(void *), int period)
st->arg = arg;
st->period = period;
timeout_set(&st->timeout, sensor_task_tick, st);
+ task_set(&st->task, sensor_task_work, st, NULL);
+ rw_init(&st->lock, "sensor");
sensor_task_tick(st);
@@ -208,59 +211,39 @@ sensor_task_register(void *arg, void (*func)(void *), int period)
void
sensor_task_unregister(struct sensor_task *st)
{
- timeout_del(&st->timeout);
-
- switch (st->state) {
- case ST_TICKING:
- free(st, M_DEVBUF);
- break;
-
- case ST_WORKQ:
- st->state = ST_DYING;
- break;
+ /*
+ * we can't reliably timeout_del or task_del because there's a window
+ * between when they come off the lists and the timeout or task code
+ * actually runs the respective handlers for them. mark the sensor_task
+ * as dying by setting period to 0 and let sensor_task_work mop up.
+ */
- case ST_RUNNING:
- st->state = ST_DYING;
- while (st->state != ST_DEAD)
- tsleep(st, 0, "stunr", 0);
- free(st, M_DEVBUF);
- break;
- default:
- panic("sensor_task_unregister: unexpected state %d",
- st->state);
- }
+ rw_enter_write(&st->lock);
+ st->period = 0;
+ rw_exit_write(&st->lock);
}
void
sensor_task_tick(void *arg)
{
struct sensor_task *st = arg;
-
- /* try to schedule the task */
- if (workq_add_task(NULL, 0, sensor_task_work, st, NULL) != 0)
- timeout_add_msec(&st->timeout, 500);
-
- st->state = ST_WORKQ;
+ task_add(systq, &st->task);
}
void
sensor_task_work(void *xst, void *arg)
{
struct sensor_task *st = xst;
+ unsigned int period = 0;
- if (st->state == ST_DYING) {
- free(st, M_DEVBUF);
- return;
- }
-
- st->state = ST_RUNNING;
- st->func(st->arg);
+ rw_enter_write(&st->lock);
+ period = st->period;
+ if (period > 0)
+ st->func(st->arg);
+ rw_exit_write(&st->lock);
- if (st->state == ST_DYING) {
- st->state = ST_DEAD;
- wakeup(st);
- } else {
- st->state = ST_TICKING;
- timeout_add_sec(&st->timeout, st->period);
- }
+ if (period == 0)
+ free(st, M_DEVBUF);
+ else
+ timeout_add_sec(&st->timeout, period);
}