opensolaris_taskq.c revision 206838
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 206838 2010-04-19 09:03:36Z delphij $"); 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 43196295Spjdstruct ostask { 44196295Spjd struct task ost_task; 45196295Spjd task_func_t *ost_func; 46196295Spjd void *ost_arg; 47196295Spjd}; 48196295Spjd 49196295Spjdtaskq_t *system_taskq = NULL; 50196295Spjd 51196295Spjdstatic void 52196295Spjdsystem_taskq_init(void *arg) 53196295Spjd{ 54196295Spjd 55196295Spjd taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask), 56196295Spjd NULL, NULL, NULL, NULL, 0, 0); 57206838Sdelphij system_taskq = taskq_create("system_taskq", mp_ncpus, 0, 0, 0, 0); 58196295Spjd} 59196295SpjdSYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL); 60196295Spjd 61196295Spjdstatic void 62196295Spjdsystem_taskq_fini(void *arg) 63196295Spjd{ 64196295Spjd 65206838Sdelphij taskq_destroy(system_taskq); 66196295Spjd uma_zdestroy(taskq_zone); 67196295Spjd} 68196295SpjdSYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL); 69196295Spjd 70196295Spjdtaskq_t * 71196295Spjdtaskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused, 72196295Spjd int maxalloc __unused, uint_t flags) 73196295Spjd{ 74196295Spjd taskq_t *tq; 75196295Spjd 76206838Sdelphij if ((flags & TASKQ_THREADS_CPU_PCT) != 0) 77206838Sdelphij nthreads = MAX((mp_ncpus * nthreads) / 100, 1); 78196295Spjd 79196295Spjd tq = kmem_alloc(sizeof(*tq), KM_SLEEP); 80196295Spjd tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue, 81196295Spjd &tq->tq_queue); 82196295Spjd (void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, name); 83196295Spjd 84196295Spjd return ((taskq_t *)tq); 85196295Spjd} 86196295Spjd 87206838Sdelphijtaskq_t * 88206838Sdelphijtaskq_create_proc(const char *name, int nthreads, pri_t pri, int minalloc, 89206838Sdelphij int maxalloc, proc_t *proc __unused, uint_t flags) 90206838Sdelphij{ 91206838Sdelphij 92206838Sdelphij return (taskq_create(name, nthreads, pri, minalloc, maxalloc, flags)); 93206838Sdelphij} 94206838Sdelphij 95196295Spjdvoid 96196295Spjdtaskq_destroy(taskq_t *tq) 97196295Spjd{ 98196295Spjd 99196295Spjd taskqueue_free(tq->tq_queue); 100196295Spjd kmem_free(tq, sizeof(*tq)); 101196295Spjd} 102196295Spjd 103196295Spjdint 104196295Spjdtaskq_member(taskq_t *tq, kthread_t *thread) 105196295Spjd{ 106196295Spjd 107196295Spjd return (taskqueue_member(tq->tq_queue, thread)); 108196295Spjd} 109196295Spjd 110196295Spjdstatic void 111196295Spjdtaskq_run(void *arg, int pending __unused) 112196295Spjd{ 113196295Spjd struct ostask *task = arg; 114196295Spjd 115196295Spjd task->ost_func(task->ost_arg); 116196295Spjd 117196295Spjd uma_zfree(taskq_zone, task); 118196295Spjd} 119196295Spjd 120196295Spjdtaskqid_t 121196295Spjdtaskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) 122196295Spjd{ 123196295Spjd struct ostask *task; 124196295Spjd int mflag; 125196295Spjd 126196295Spjd if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP) 127196295Spjd mflag = M_WAITOK; 128196295Spjd else 129196295Spjd mflag = M_NOWAIT; 130196295Spjd 131196295Spjd task = uma_zalloc(taskq_zone, mflag); 132196295Spjd if (task == NULL) 133196295Spjd return (0); 134196295Spjd 135196295Spjd task->ost_func = func; 136196295Spjd task->ost_arg = arg; 137196295Spjd 138196295Spjd TASK_INIT(&task->ost_task, 0, taskq_run, task); 139196295Spjd taskqueue_enqueue(tq->tq_queue, &task->ost_task); 140196295Spjd 141196295Spjd return ((taskqid_t)(void *)task); 142196295Spjd} 143