/* $NetBSD$ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Taylor R. Campbell. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``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 THE FOUNDATION OR CONTRIBUTORS * 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 _SYS_TASK_H_ #define _SYS_TASK_H_ #include #include #include #include struct task; struct taskqueue; struct taskworker; struct delayed_task; typedef void task_fn_t(struct task *); struct task { struct taskworker *volatile task_worker; task_fn_t *task_fn; TAILQ_ENTRY(task) task_entry; }; typedef void delayed_task_fn_t(struct delayed_task *); struct delayed_task { struct task dt_task; struct callout dt_callout; }; static inline void task_init(struct task *task, task_fn_t *fn) { task->task_worker = NULL; task->task_fn = fn; } void task_destroy(struct task *); void task_done(struct task *); void task_schedule(struct task *); bool task_cancel(struct task *, kmutex_t *); bool task_cancel_async(struct task *); /* Not part of the API -- don't use this outside delayed_task_init. */ void delayed_task_timeout(void *); static inline void delayed_task_init(struct delayed_task *dt, task_fn_t *fn) { /* * XXX Sketchy function cast from void (*)(struct task *) to * void (*)(struct delayed_task *). The memory addresses of * the arguments will be the same. Is this kosher? If not, * the API can be adapted, but it's nicer this way. */ task_init(&dt->dt_task, (task_fn_t *)fn); callout_init(&dt->dt_callout, CALLOUT_MPSAFE); callout_setfunc(&dt->dt_callout, delayed_task_timeout, dt); } void delayed_task_destroy(struct delayed_task *); bool delayed_task_timedout(struct delayed_task *); typedef uint64_t nsec_t; typedef uint32_t jitter_t; void delayed_task_schedule(struct delayed_task *, nsec_t, jitter_t); bool delayed_task_reschedule(struct delayed_task *, nsec_t, jitter_t); bool delayed_task_cancel(struct delayed_task *, kmutex_t *); bool delayed_task_cancel_async(struct delayed_task *); #define TASKQUEUE_PERCPU 0x01 /* PRI_NONE task queue, always available. */ extern struct taskqueue *system_taskqueue; int taskqueue_get(struct taskqueue **, pri_t); void taskqueue_put(struct taskqueue *); int taskqueue_create(struct taskqueue **, const char *, pri_t, int, int); void taskqueue_destroy(struct taskqueue *); void taskqueue_schedule(struct taskqueue *, struct task *); void taskqueue_schedule_delayed(struct taskqueue *, struct delayed_task *, nsec_t, jitter_t); void taskqueue_drain(struct taskqueue *); void tasks_init(void); #endif /* _SYS_TASK_H_ */