opensolaris_taskq.c revision 213791
1196295Spjd/*- 2196295Spjd * Copyright (c) 2009 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3196295Spjd * All rights reserved. 4196295Spjd * 5196295Spjd * Redistribution and use in source and binary forms, with or without 6196295Spjd * modification, are permitted provided that the following conditions 7196295Spjd * are met: 8196295Spjd * 1. Redistributions of source code must retain the above copyright 9196295Spjd * notice, this list of conditions and the following disclaimer. 10196295Spjd * 2. Redistributions in binary form must reproduce the above copyright 11196295Spjd * notice, this list of conditions and the following disclaimer in the 12196295Spjd * documentation and/or other materials provided with the distribution. 13196295Spjd * 14196295Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15196295Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16196295Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17196295Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18196295Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19196295Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20196295Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21196295Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22196295Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23196295Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24196295Spjd * SUCH DAMAGE. 25196295Spjd */ 26196295Spjd 27196295Spjd#include <sys/cdefs.h> 28196295Spjd__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c 213791 2010-10-13 17:13:43Z rpaulo $"); 29196295Spjd 30196295Spjd#include <sys/param.h> 31196295Spjd#include <sys/kernel.h> 32196295Spjd#include <sys/kmem.h> 33196295Spjd#include <sys/lock.h> 34196295Spjd#include <sys/mutex.h> 35196295Spjd#include <sys/queue.h> 36196295Spjd#include <sys/taskqueue.h> 37196295Spjd#include <sys/taskq.h> 38196295Spjd 39196295Spjd#include <vm/uma.h> 40196295Spjd 41196295Spjdstatic uma_zone_t taskq_zone; 42196295Spjd 43196295Spjdtaskq_t *system_taskq = NULL; 44196295Spjd 45196295Spjdstatic void 46196295Spjdsystem_taskq_init(void *arg) 47196295Spjd{ 48196295Spjd 49196295Spjd taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask), 50196295Spjd NULL, NULL, NULL, NULL, 0, 0); 51206838Sdelphij system_taskq = taskq_create("system_taskq", mp_ncpus, 0, 0, 0, 0); 52196295Spjd} 53196295SpjdSYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL); 54196295Spjd 55196295Spjdstatic void 56196295Spjdsystem_taskq_fini(void *arg) 57196295Spjd{ 58196295Spjd 59206838Sdelphij taskq_destroy(system_taskq); 60196295Spjd uma_zdestroy(taskq_zone); 61196295Spjd} 62196295SpjdSYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL); 63196295Spjd 64196295Spjdtaskq_t * 65196295Spjdtaskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused, 66196295Spjd int maxalloc __unused, uint_t flags) 67196295Spjd{ 68196295Spjd taskq_t *tq; 69196295Spjd 70206838Sdelphij if ((flags & TASKQ_THREADS_CPU_PCT) != 0) 71206838Sdelphij nthreads = MAX((mp_ncpus * nthreads) / 100, 1); 72196295Spjd 73196295Spjd tq = kmem_alloc(sizeof(*tq), KM_SLEEP); 74196295Spjd tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue, 75196295Spjd &tq->tq_queue); 76213791Srpaulo (void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, "%s", name); 77196295Spjd 78196295Spjd return ((taskq_t *)tq); 79196295Spjd} 80196295Spjd 81206838Sdelphijtaskq_t * 82206838Sdelphijtaskq_create_proc(const char *name, int nthreads, pri_t pri, int minalloc, 83206838Sdelphij int maxalloc, proc_t *proc __unused, uint_t flags) 84206838Sdelphij{ 85206838Sdelphij 86206838Sdelphij return (taskq_create(name, nthreads, pri, minalloc, maxalloc, flags)); 87206838Sdelphij} 88206838Sdelphij 89196295Spjdvoid 90196295Spjdtaskq_destroy(taskq_t *tq) 91196295Spjd{ 92196295Spjd 93196295Spjd taskqueue_free(tq->tq_queue); 94196295Spjd kmem_free(tq, sizeof(*tq)); 95196295Spjd} 96196295Spjd 97196295Spjdint 98196295Spjdtaskq_member(taskq_t *tq, kthread_t *thread) 99196295Spjd{ 100196295Spjd 101196295Spjd return (taskqueue_member(tq->tq_queue, thread)); 102196295Spjd} 103196295Spjd 104196295Spjdstatic void 105196295Spjdtaskq_run(void *arg, int pending __unused) 106196295Spjd{ 107196295Spjd struct ostask *task = arg; 108196295Spjd 109196295Spjd task->ost_func(task->ost_arg); 110196295Spjd 111196295Spjd uma_zfree(taskq_zone, task); 112196295Spjd} 113196295Spjd 114196295Spjdtaskqid_t 115196295Spjdtaskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) 116196295Spjd{ 117196295Spjd struct ostask *task; 118196295Spjd int mflag; 119196295Spjd 120196295Spjd if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP) 121196295Spjd mflag = M_WAITOK; 122196295Spjd else 123196295Spjd mflag = M_NOWAIT; 124196295Spjd 125196295Spjd task = uma_zalloc(taskq_zone, mflag); 126196295Spjd if (task == NULL) 127196295Spjd return (0); 128196295Spjd 129196295Spjd task->ost_func = func; 130196295Spjd task->ost_arg = arg; 131196295Spjd 132196295Spjd TASK_INIT(&task->ost_task, 0, taskq_run, task); 133196295Spjd taskqueue_enqueue(tq->tq_queue, &task->ost_task); 134196295Spjd 135196295Spjd return ((taskqid_t)(void *)task); 136196295Spjd} 137208147Spjd 138208147Spjd#define TASKQ_MAGIC 0x74541c 139208147Spjd 140208147Spjdstatic void 141208147Spjdtaskq_run_safe(void *arg, int pending __unused) 142208147Spjd{ 143208147Spjd struct ostask *task = arg; 144208147Spjd 145208147Spjd ASSERT(task->ost_magic == TASKQ_MAGIC); 146208147Spjd task->ost_func(task->ost_arg); 147208147Spjd task->ost_magic = 0; 148208147Spjd} 149208147Spjd 150208147Spjdtaskqid_t 151208147Spjdtaskq_dispatch_safe(taskq_t *tq, task_func_t func, void *arg, 152208147Spjd struct ostask *task) 153208147Spjd{ 154208147Spjd 155208147Spjd ASSERT(task->ost_magic != TASKQ_MAGIC); 156208147Spjd 157208147Spjd task->ost_magic = TASKQ_MAGIC; 158208147Spjd task->ost_func = func; 159208147Spjd task->ost_arg = arg; 160208147Spjd 161208147Spjd TASK_INIT(&task->ost_task, 0, taskq_run_safe, task); 162208147Spjd taskqueue_enqueue(tq->tq_queue, &task->ost_task); 163208147Spjd 164208147Spjd return ((taskqid_t)(void *)task); 165208147Spjd} 166