summaryrefslogtreecommitdiff
path: root/sys/kern/kern_sensors.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_sensors.c')
-rw-r--r--sys/kern/kern_sensors.c160
1 files changed, 72 insertions, 88 deletions
diff --git a/sys/kern/kern_sensors.c b/sys/kern/kern_sensors.c
index 798cd7789b5..54384ee0e0a 100644
--- a/sys/kern/kern_sensors.c
+++ b/sys/kern/kern_sensors.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sensors.c,v 1.19 2007/06/04 18:42:05 deraadt Exp $ */
+/* $OpenBSD: kern_sensors.c,v 1.20 2007/06/24 05:34:35 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -18,37 +18,23 @@
*/
#include <sys/param.h>
+#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-#include <sys/kthread.h>
#include <sys/queue.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/device.h>
#include <sys/hotplug.h>
+#include <sys/timeout.h>
+#include <sys/workq.h>
#include <sys/sensors.h>
#include "hotplug.h"
int sensordev_count = 0;
-SLIST_HEAD(, ksensordev) sensordev_list = SLIST_HEAD_INITIALIZER(sensordev_list);
-
-struct sensor_task {
- void *arg;
- void (*func)(void *);
-
- 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 *);
-
-TAILQ_HEAD(, sensor_task) tasklist = TAILQ_HEAD_INITIALIZER(tasklist);
+SLIST_HEAD(, ksensordev) sensordev_list =
+ SLIST_HEAD_INITIALIZER(sensordev_list);
void
sensordev_install(struct ksensordev *sensdev)
@@ -176,100 +162,98 @@ sensor_find(int dev, enum sensor_type type, int numt)
return (NULL);
}
-int
+struct sensor_task {
+ void (*func)(void *);
+ void *arg;
+
+ int period;
+ struct timeout timeout;
+ volatile enum {
+ ST_TICKING,
+ ST_WORKQ,
+ ST_RUNNING,
+ ST_DYING,
+ ST_DEAD
+ } state;
+};
+
+void sensor_task_tick(void *);
+void sensor_task_work(void *, void *);
+
+struct sensor_task *
sensor_task_register(void *arg, void (*func)(void *), int period)
{
- struct sensor_task *st;
+ struct sensor_task *st;
st = malloc(sizeof(struct sensor_task), M_DEVBUF, M_NOWAIT);
if (st == NULL)
- return (1);
+ return (NULL);
- st->arg = arg;
st->func = func;
+ st->arg = arg;
st->period = period;
+ timeout_set(&st->timeout, sensor_task_tick, st);
- st->running = 1;
+ sensor_task_tick(st);
- if (TAILQ_EMPTY(&tasklist))
- kthread_create_deferred(sensor_task_create, NULL);
-
- st->nextrun = 0;
- TAILQ_INSERT_HEAD(&tasklist, st, entry);
- wakeup(&tasklist);
-
- return (0);
+ return (st);
}
void
-sensor_task_unregister(void *arg)
+sensor_task_unregister(struct sensor_task *st)
{
- struct sensor_task *st;
-
- TAILQ_FOREACH(st, &tasklist, entry) {
- if (st->arg == arg)
- st->running = 0;
+ timeout_del(&st->timeout);
+
+ switch (st->state) {
+ case ST_TICKING:
+ free(st, M_DEVBUF);
+ break;
+
+ case ST_WORKQ:
+ st->state = ST_DYING;
+ break;
+
+ case ST_RUNNING:
+ st->state = ST_DYING;
+ while (st->state != ST_DEAD)
+ tsleep(st, 0, "stunr", 0);
+ break;
+ default:
+ panic("sensor_task_unregister: unexpected state %d",
+ st->state);
}
}
void
-sensor_task_create(void *arg)
-{
- if (kthread_create(sensor_task_thread, NULL, NULL, "sensors") != 0)
- panic("sensors kthread");
-}
-
-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);
+ struct sensor_task *st = arg;
- while ((st = nst) != NULL) {
- nst = TAILQ_NEXT(st, entry);
-
- if (st->nextrun > now)
- break;
+ /* try to schedule the task */
+ if (workq_add_task(NULL, 0, sensor_task_work, st, NULL) != 0)
+ timeout_add(&st->timeout, hz/2);
- /* take it out while we work on it */
- TAILQ_REMOVE(&tasklist, st, entry);
-
- if (!st->running) {
- free(st, M_DEVBUF);
- continue;
- }
-
- /* run the task */
- st->func(st->arg);
- /* stick it back in the tasklist */
- sensor_task_schedule(st);
- }
- }
-
- kthread_exit(0);
+ st->state = ST_WORKQ;
}
void
-sensor_task_schedule(struct sensor_task *st)
+sensor_task_work(void *xst, void *arg)
{
- struct sensor_task *cst;
-
- st->nextrun = time_uptime + st->period;
+ struct sensor_task *st = xst;
- TAILQ_FOREACH(cst, &tasklist, entry) {
- if (cst->nextrun > st->nextrun) {
- TAILQ_INSERT_BEFORE(cst, st, entry);
- return;
- }
+ if (st->state == ST_DYING) {
+ free(st, M_DEVBUF);
+ return;
}
- /* must be an empty list, or at the end of the list */
- TAILQ_INSERT_TAIL(&tasklist, st, entry);
-}
+ st->state = ST_RUNNING;
+ st->func(st->arg);
+ if (st->state == ST_DYING) {
+ st->state = ST_DEAD;
+ wakeup(st);
+ } else {
+ st->state = ST_TICKING;
+ timeout_add(&st->timeout, hz * st->period);
+ }
+}