diff options
author | 2013-11-04 00:25:14 +0000 | |
---|---|---|
committer | 2013-11-04 00:25:14 +0000 | |
commit | b3316ca552a809646a88f890c5207abe7eb30601 (patch) | |
tree | 705c0ca3b592f9b32143f8885a3e43e2767ab6ea /sys | |
parent | Simplify jme_miibus_readreg() / jme_miibus_writereg() a bit by using the (diff) | |
download | wireguard-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.c | 85 |
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); } |