opensolaris_taskq.c revision 219089
1181643Skmacy/*- 2181643Skmacy * Copyright (c) 2009 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3181643Skmacy * All rights reserved. 4181643Skmacy * 5181643Skmacy * Redistribution and use in source and binary forms, with or without 6181643Skmacy * modification, are permitted provided that the following conditions 7181643Skmacy * are met: 8181643Skmacy * 1. Redistributions of source code must retain the above copyright 9181643Skmacy * notice, this list of conditions and the following disclaimer. 10181643Skmacy * 2. Redistributions in binary form must reproduce the above copyright 11181643Skmacy * notice, this list of conditions and the following disclaimer in the 12181643Skmacy * documentation and/or other materials provided with the distribution. 13181643Skmacy * 14181643Skmacy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15181643Skmacy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16181643Skmacy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17181643Skmacy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18181643Skmacy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19181643Skmacy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20181643Skmacy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21181643Skmacy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22181643Skmacy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23181643Skmacy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24181643Skmacy * SUCH DAMAGE. 25181643Skmacy */ 26181643Skmacy 27181643Skmacy#include <sys/cdefs.h> 28181643Skmacy__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c 219089 2011-02-27 19:41:40Z pjd $"); 29181643Skmacy 30181643Skmacy#include <sys/param.h> 31181643Skmacy#include <sys/kernel.h> 32181643Skmacy#include <sys/kmem.h> 33181643Skmacy#include <sys/lock.h> 34181643Skmacy#include <sys/mutex.h> 35181643Skmacy#include <sys/queue.h> 36181643Skmacy#include <sys/taskqueue.h> 37181643Skmacy#include <sys/taskq.h> 38181643Skmacy 39181643Skmacy#include <vm/uma.h> 40181643Skmacy 41181643Skmacystatic uma_zone_t taskq_zone; 42181643Skmacy 43186557Skmacytaskq_t *system_taskq = NULL; 44181643Skmacy 45186557Skmacystatic void 46186557Skmacysystem_taskq_init(void *arg) 47181643Skmacy{ 48185605Skmacy 49185605Skmacy taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask), 50181643Skmacy NULL, NULL, NULL, NULL, 0, 0); 51181643Skmacy system_taskq = taskq_create("system_taskq", mp_ncpus, 0, 0, 0, 0); 52181643Skmacy} 53181643SkmacySYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL); 54181643Skmacy 55181643Skmacystatic void 56181643Skmacysystem_taskq_fini(void *arg) 57185605Skmacy{ 58185605Skmacy 59181643Skmacy taskq_destroy(system_taskq); 60181643Skmacy uma_zdestroy(taskq_zone); 61181643Skmacy} 62181643SkmacySYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL); 63185605Skmacy 64185605Skmacytaskq_t * 65185605Skmacytaskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused, 66185605Skmacy int maxalloc __unused, uint_t flags) 67185605Skmacy{ 68181643Skmacy taskq_t *tq; 69181643Skmacy 70181643Skmacy if ((flags & TASKQ_THREADS_CPU_PCT) != 0) 71181643Skmacy nthreads = MAX((mp_ncpus * nthreads) / 100, 1); 72181643Skmacy 73181643Skmacy tq = kmem_alloc(sizeof(*tq), KM_SLEEP); 74181643Skmacy tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue, 75181643Skmacy &tq->tq_queue); 76181643Skmacy (void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, "%s", name); 77181643Skmacy 78181643Skmacy return ((taskq_t *)tq); 79181643Skmacy} 80181643Skmacy 81181643Skmacytaskq_t * 82181643Skmacytaskq_create_proc(const char *name, int nthreads, pri_t pri, int minalloc, 83181643Skmacy int maxalloc, proc_t *proc __unused, uint_t flags) 84181643Skmacy{ 85181643Skmacy 86181643Skmacy return (taskq_create(name, nthreads, pri, minalloc, maxalloc, flags)); 87181643Skmacy} 88181643Skmacy 89181643Skmacyvoid 90181643Skmacytaskq_destroy(taskq_t *tq) 91181643Skmacy{ 92181643Skmacy 93181643Skmacy taskqueue_free(tq->tq_queue); 94181643Skmacy kmem_free(tq, sizeof(*tq)); 95181643Skmacy} 96181643Skmacy 97181643Skmacyint 98181643Skmacytaskq_member(taskq_t *tq, kthread_t *thread) 99181643Skmacy{ 100181643Skmacy 101181643Skmacy return (taskqueue_member(tq->tq_queue, thread)); 102181643Skmacy} 103181643Skmacy 104181643Skmacystatic void 105181643Skmacytaskq_run(void *arg, int pending __unused) 106181643Skmacy{ 107181643Skmacy struct ostask *task = arg; 108181643Skmacy 109181643Skmacy task->ost_func(task->ost_arg); 110181643Skmacy 111181643Skmacy uma_zfree(taskq_zone, task); 112181643Skmacy} 113181643Skmacy 114181643Skmacytaskqid_t 115181643Skmacytaskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) 116181643Skmacy{ 117181643Skmacy struct ostask *task; 118181643Skmacy int mflag, prio; 119181643Skmacy 120181643Skmacy if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP) 121181643Skmacy mflag = M_WAITOK; 122181643Skmacy else 123181643Skmacy mflag = M_NOWAIT; 124181643Skmacy /* 125181643Skmacy * If TQ_FRONT is given, we want higher priority for this task, so it 126181643Skmacy * can go at the front of the queue. 127181643Skmacy */ 128181643Skmacy prio = !!(flags & TQ_FRONT); 129181643Skmacy 130181643Skmacy task = uma_zalloc(taskq_zone, mflag); 131181643Skmacy if (task == NULL) 132181643Skmacy return (0); 133181643Skmacy 134181643Skmacy task->ost_func = func; 135181805Skmacy task->ost_arg = arg; 136181805Skmacy 137181643Skmacy TASK_INIT(&task->ost_task, prio, taskq_run, task); 138181643Skmacy taskqueue_enqueue(tq->tq_queue, &task->ost_task); 139181643Skmacy 140181643Skmacy return ((taskqid_t)(void *)task); 141181643Skmacy} 142185605Skmacy 143185605Skmacy#define TASKQ_MAGIC 0x74541c 144185605Skmacy 145185605Skmacystatic void 146185605Skmacytaskq_run_safe(void *arg, int pending __unused) 147185605Skmacy{ 148185605Skmacy struct ostask *task = arg; 149185605Skmacy 150185605Skmacy ASSERT(task->ost_magic == TASKQ_MAGIC); 151185605Skmacy task->ost_func(task->ost_arg); 152185605Skmacy task->ost_magic = 0; 153185605Skmacy} 154185605Skmacy 155185605Skmacytaskqid_t 156185605Skmacytaskq_dispatch_safe(taskq_t *tq, task_func_t func, void *arg, u_int flags, 157185605Skmacy struct ostask *task) 158185605Skmacy{ 159185605Skmacy int prio; 160185605Skmacy 161185605Skmacy ASSERT(task->ost_magic != TASKQ_MAGIC); 162185605Skmacy 163185605Skmacy /* 164185605Skmacy * If TQ_FRONT is given, we want higher priority for this task, so it 165185605Skmacy * can go at the front of the queue. 166185605Skmacy */ 167185605Skmacy prio = !!(flags & TQ_FRONT); 168185605Skmacy 169185605Skmacy task->ost_magic = TASKQ_MAGIC; 170185605Skmacy task->ost_func = func; 171185605Skmacy task->ost_arg = arg; 172185605Skmacy 173185605Skmacy TASK_INIT(&task->ost_task, prio, taskq_run_safe, task); 174185605Skmacy taskqueue_enqueue(tq->tq_queue, &task->ost_task); 175185605Skmacy 176185605Skmacy return ((taskqid_t)(void *)task); 177185605Skmacy} 178185605Skmacy