diff options
| author | thorpej <thorpej@NetBSD.org> | 2003-04-20 20:20:35 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2003-04-20 20:20:35 +0000 |
| commit | d14efd22d1275a2228bc58824f71f91d83ba12c6 (patch) | |
| tree | f4d08801e2e60568e9900aa7cf42129bab62eaa8 /sys/dev | |
| parent | c71d457343bd51740f066d5c85d2ebd859f745f2 (diff) | |
Generic "task queue" for sysmon back-ends. This provides a thread
context for callbacks that require it in order to handle sysmon-related
events.
Adapted from the "OsdSchedule" bits of the ACPI code.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/sysmon/files.sysmon | 5 | ||||
| -rw-r--r-- | sys/dev/sysmon/sysmon_taskq.c | 232 | ||||
| -rw-r--r-- | sys/dev/sysmon/sysmon_taskq.h | 45 |
3 files changed, 281 insertions, 1 deletions
diff --git a/sys/dev/sysmon/files.sysmon b/sys/dev/sysmon/files.sysmon index 2e0deccbcfa..565923425ee 100644 --- a/sys/dev/sysmon/files.sysmon +++ b/sys/dev/sysmon/files.sysmon @@ -1,4 +1,4 @@ -# $NetBSD: files.sysmon,v 1.2 2003/04/17 01:02:21 thorpej Exp $ +# $NetBSD: files.sysmon,v 1.3 2003/04/20 20:20:35 thorpej Exp $ define sysmon_envsys file dev/sysmon/sysmon_envsys.c sysmon_envsys needs-flag @@ -11,3 +11,6 @@ file dev/sysmon/sysmon_power.c sysmon_power needs-flag file dev/sysmon/sysmon.c sysmon_envsys | sysmon_wdog | sysmon_power + +define sysmon_taskq +file dev/sysmon/sysmon_taskq.c sysmon_taskq diff --git a/sys/dev/sysmon/sysmon_taskq.c b/sys/dev/sysmon/sysmon_taskq.c new file mode 100644 index 00000000000..38478148d19 --- /dev/null +++ b/sys/dev/sysmon/sysmon_taskq.c @@ -0,0 +1,232 @@ +/* $NetBSD: sysmon_taskq.c,v 1.1 2003/04/20 20:20:35 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * General purpose task queue for sysmon back-ends. This can be + * used to run callbacks that require thread context. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/queue.h> +#include <sys/proc.h> +#include <sys/kthread.h> +#include <sys/systm.h> + +#include <dev/sysmon/sysmon_taskq.h> + +struct sysmon_task { + TAILQ_ENTRY(sysmon_task) st_list; + void (*st_func)(void *); + void *st_arg; + u_int st_pri; +}; + +static TAILQ_HEAD(, sysmon_task) sysmon_task_queue = + TAILQ_HEAD_INITIALIZER(sysmon_task_queue); +struct simplelock sysmon_task_queue_slock = SIMPLELOCK_INITIALIZER; + +#define SYSMON_TASK_QUEUE_LOCK(s) \ +do { \ + s = splsched(); \ + simple_lock(&sysmon_task_queue_slock); \ +} while (/*CONSTCOND*/0) + +#define SYSMON_TASK_QUEUE_UNLOCK(s) \ +do { \ + simple_unlock(&sysmon_task_queue_slock); \ + splx((s)); \ +} while (/*CONSTCOND*/0) + +static __volatile int sysmon_task_queue_cleanup_sem; + +static struct proc *sysmon_task_queue_proc; + +static void sysmon_task_queue_create_thread(void *); +static void sysmon_task_queue_thread(void *); + +static struct simplelock sysmon_task_queue_initialized_slock = + SIMPLELOCK_INITIALIZER; +static int sysmon_task_queue_initialized; + +/* + * sysmon_task_queue_init: + * + * Initialize the sysmon task queue. + */ +void +sysmon_task_queue_init(void) +{ + + simple_lock(&sysmon_task_queue_initialized_slock); + if (sysmon_task_queue_initialized) { + simple_unlock(&sysmon_task_queue_initialized_slock); + return; + } + + sysmon_task_queue_initialized = 1; + simple_unlock(&sysmon_task_queue_initialized_slock); + + kthread_create(sysmon_task_queue_create_thread, NULL); +} + +/* + * sysmon_task_queue_fini: + * + * Tear town the sysmon task queue. + */ +void +sysmon_task_queue_fini(void) +{ + int s; + + SYSMON_TASK_QUEUE_LOCK(s); + + sysmon_task_queue_cleanup_sem = 1; + wakeup(&sysmon_task_queue); + + while (sysmon_task_queue_cleanup_sem != 0) { + (void) ltsleep((void *) &sysmon_task_queue_cleanup_sem, + PVM, "stfini", 0, &sysmon_task_queue_slock); + } + + SYSMON_TASK_QUEUE_UNLOCK(s); +} + +/* + * sysmon_task_queue_create_thread: + * + * Create the sysmon task queue execution thread. + */ +static void +sysmon_task_queue_create_thread(void *arg) +{ + int error; + + error = kthread_create1(sysmon_task_queue_thread, NULL, + &sysmon_task_queue_proc, "sysmon taskq"); + if (error) { + printf("Unable to create sysmon task queue thread, " + "error = %d\n", error); + panic("sysmon_task_queue_create_thread"); + } +} + +/* + * sysmon_task_queue_thread: + * + * The sysmon task queue execution thread. We execute callbacks that + * have been queued for us. + */ +static void +sysmon_task_queue_thread(void *arg) +{ + struct sysmon_task *st; + int s; + + /* + * Run through all the tasks before we check for the exit + * condition; it's probably more important to actually run + * all the tasks before we exit. + */ + for (;;) { + SYSMON_TASK_QUEUE_LOCK(s); + st = TAILQ_FIRST(&sysmon_task_queue); + if (st == NULL) { + /* Check for the exit condition. */ + if (sysmon_task_queue_cleanup_sem != 0) { + /* Time to die. */ + sysmon_task_queue_cleanup_sem = 0; + wakeup((void *) &sysmon_task_queue_cleanup_sem); + SYSMON_TASK_QUEUE_UNLOCK(s); + kthread_exit(0); + } + (void) ltsleep(&sysmon_task_queue, PVM, + "smtaskq", 0, &sysmon_task_queue_slock); + SYSMON_TASK_QUEUE_UNLOCK(s); + continue; + } + TAILQ_REMOVE(&sysmon_task_queue, st, st_list); + SYSMON_TASK_QUEUE_UNLOCK(s); + + (*st->st_func)(st->st_arg); + free(st, M_TEMP); + } + panic("sysmon_task_queue_thread: impossible"); +} + +/* + * sysmon_task_queue_sched: + * + * Schedule a task for deferred execution. + */ +int +sysmon_task_queue_sched(u_int pri, void (*func)(void *), void *arg) +{ + struct sysmon_task *st, *lst; + int s; + + if (sysmon_task_queue_proc == NULL) + printf("WARNING: Callback scheduled before sysmon task queue " + "thread present.\n"); + + if (func == NULL) + return (EINVAL); + + st = malloc(sizeof(*st), M_TEMP, M_NOWAIT); + if (st == NULL) + return (ENOMEM); + + st->st_func = func; + st->st_arg = arg; + st->st_pri = pri; + + SYSMON_TASK_QUEUE_LOCK(s); + TAILQ_FOREACH(lst, &sysmon_task_queue, st_list) { + if (st->st_pri > lst->st_pri) { + TAILQ_INSERT_BEFORE(lst, st, st_list); + break; + } + } + if (lst == NULL) + TAILQ_INSERT_TAIL(&sysmon_task_queue, st, st_list); + wakeup(&sysmon_task_queue); + SYSMON_TASK_QUEUE_UNLOCK(s); + + return (0); +} diff --git a/sys/dev/sysmon/sysmon_taskq.h b/sys/dev/sysmon/sysmon_taskq.h new file mode 100644 index 00000000000..2598103412b --- /dev/null +++ b/sys/dev/sysmon/sysmon_taskq.h @@ -0,0 +1,45 @@ +/* $NetBSD: sysmon_taskq.h,v 1.1 2003/04/20 20:20:35 thorpej Exp $ */ + +/* + * Copyright (c) 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEV_SYSMON_SYSMON_TASKQ_H_ +#define _DEV_SYSMON_SYSMON_TASKQ_H_ + +void sysmon_task_queue_init(void); +void sysmon_task_queue_fini(void); +int sysmon_task_queue_sched(u_int, void (*)(void *), void *); + +#endif /* _DEV_SYSMON_SYSMON_TASKQ_H_ */ |
