summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2007-06-01 04:15:46 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2007-06-01 04:15:46 +0000
commitd7f3b01f971e332b79ee0f23c84b552600423d8e (patch)
tree71bb6274b20b3e0b8a4c1ccf1b908934a34148d6 /sys/kern
parent029d51b61739e9b9d4d58f1ae4a08d32279cc976 (diff)
rework the sensor task handling to run in the kernels generic workq.
apologies to art for abusing timeouts so badly. apologies to tedu for making his head hurt. tested by and ok tedu@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sensors.c115
1 files changed, 65 insertions, 50 deletions
diff --git a/sys/kern/kern_sensors.c b/sys/kern/kern_sensors.c
index cc198160998..1870c631862 100644
--- a/sys/kern/kern_sensors.c
+++ b/sys/kern/kern_sensors.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sensors.c,v 1.17 2007/03/22 16:55:31 deraadt Exp $ */
+/* $OpenBSD: kern_sensors.c,v 1.18 2007/06/01 04:15:45 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -27,6 +27,7 @@
#include <sys/time.h>
#include <sys/device.h>
#include <sys/hotplug.h>
+#include <sys/workq.h>
#include <sys/sensors.h>
#include "hotplug.h"
@@ -35,20 +36,21 @@ int sensordev_count = 0;
SLIST_HEAD(, ksensordev) sensordev_list = SLIST_HEAD_INITIALIZER(sensordev_list);
struct sensor_task {
- void *arg;
void (*func)(void *);
+ void *arg;
int period;
time_t nextrun;
- volatile int running;
TAILQ_ENTRY(sensor_task) entry;
};
-void sensor_task_create(void *);
-void sensor_task_thread(void *);
-void sensor_task_schedule(struct sensor_task *);
+struct timeout sensor_task_to;
+TAILQ_HEAD(, sensor_task) sensor_task_list =
+ TAILQ_HEAD_INITIALIZER(sensor_task_list);
-TAILQ_HEAD(, sensor_task) tasklist = TAILQ_HEAD_INITIALIZER(tasklist);
+void sensor_task_tick(void *);
+void sensor_task_schedule(struct sensor_task *);
+void sensor_task_work(void *, void *);
void
sensordev_install(struct ksensordev *sensdev)
@@ -188,15 +190,16 @@ sensor_task_register(void *arg, void (*func)(void *), int period)
st->arg = arg;
st->func = func;
st->period = period;
+ st->nextrun = 0;
- st->running = 1;
+ if (TAILQ_EMPTY(&sensor_task_list))
+ timeout_set(&sensor_task_to, sensor_task_tick, NULL);
+ else
+ timeout_del(&sensor_task_to);
- if (TAILQ_EMPTY(&tasklist))
- kthread_create_deferred(sensor_task_create, NULL);
+ TAILQ_INSERT_HEAD(&sensor_task_list, st, entry);
- st->nextrun = 0;
- TAILQ_INSERT_HEAD(&tasklist, st, entry);
- wakeup(&tasklist);
+ sensor_task_tick(NULL);
return (0);
}
@@ -204,65 +207,78 @@ sensor_task_register(void *arg, void (*func)(void *), int period)
void
sensor_task_unregister(void *arg)
{
- struct sensor_task *st;
+ struct sensor_task *st, *nst;
+
+ timeout_del(&sensor_task_to);
+
+ nst = TAILQ_FIRST(&sensor_task_list);
+ while (nst != NULL) {
+ st = nst;
+ nst = TAILQ_NEXT(st, entry);
- TAILQ_FOREACH(st, &tasklist, entry) {
if (st->arg == arg)
- st->running = 0;
+ free(st, M_DEVBUF);
}
-}
-void
-sensor_task_create(void *arg)
-{
- if (kthread_create(sensor_task_thread, NULL, NULL, "sensors") != 0)
- panic("sensors kthread");
+ if (TAILQ_EMPTY(&sensor_task_list))
+ return;
+
+ sensor_task_tick(NULL);
}
void
-sensor_task_thread(void *arg)
+sensor_task_tick(void *arg)
{
struct sensor_task *st, *nst;
- time_t now;
-
- while (!TAILQ_EMPTY(&tasklist)) {
- while ((nst = TAILQ_FIRST(&tasklist))->nextrun >
- (now = time_uptime))
- tsleep(&tasklist, PWAIT, "timeout",
- (nst->nextrun - now) * hz);
+ time_t now = time_uptime;
- while ((st = nst) != NULL) {
- nst = TAILQ_NEXT(st, entry);
+#ifdef DIAGNOSTIC
+ if (TAILQ_EMPTY(&sensor_task_list))
+ panic("sensor task tick for no sensors");
+#endif
- if (st->nextrun > now)
- break;
+ nst = TAILQ_FIRST(&sensor_task_list);
+ while (nst->nextrun <= now) {
+ st = nst;
+ nst = TAILQ_NEXT(st, entry);
- /* take it out while we work on it */
- TAILQ_REMOVE(&tasklist, st, entry);
+ /* try to schedule the task */
+ if (workq_add_task(NULL, 0, sensor_task_work, st, NULL) != 0) {
+ timeout_add(&sensor_task_to, hz);
+ return;
+ }
- if (!st->running) {
- free(st, M_DEVBUF);
- continue;
- }
+ /* take it out while we work on it */
+ TAILQ_REMOVE(&sensor_task_list, st, entry);
- /* run the task */
- st->func(st->arg);
- /* stick it back in the tasklist */
- sensor_task_schedule(st);
- }
+ if (nst == NULL)
+ return;
}
- kthread_exit(0);
+ timeout_add(&sensor_task_to, (nst->nextrun - now) * hz);
+}
+
+void
+sensor_task_work(void *xst, void *arg)
+{
+ struct sensor_task *st = xst;
+
+ timeout_del(&sensor_task_to);
+
+ st->func(st->arg);
+ sensor_task_schedule(st);
+
+ sensor_task_tick(NULL);
}
void
sensor_task_schedule(struct sensor_task *st)
{
- struct sensor_task *cst;
+ struct sensor_task *cst;
st->nextrun = time_uptime + st->period;
- TAILQ_FOREACH(cst, &tasklist, entry) {
+ TAILQ_FOREACH(cst, &sensor_task_list, entry) {
if (cst->nextrun > st->nextrun) {
TAILQ_INSERT_BEFORE(cst, st, entry);
return;
@@ -270,6 +286,5 @@ sensor_task_schedule(struct sensor_task *st)
}
/* must be an empty list, or at the end of the list */
- TAILQ_INSERT_TAIL(&tasklist, st, entry);
+ TAILQ_INSERT_TAIL(&sensor_task_list, st, entry);
}
-