diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-06-01 04:15:46 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-06-01 04:15:46 +0000 |
commit | d7f3b01f971e332b79ee0f23c84b552600423d8e (patch) | |
tree | 71bb6274b20b3e0b8a4c1ccf1b908934a34148d6 /sys/kern | |
parent | 029d51b61739e9b9d4d58f1ae4a08d32279cc976 (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.c | 115 |
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); } - |