Path: blob/main/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c
48383 views
/*-1* Copyright (c) 2009 Pawel Jakub Dawidek <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <sys/kernel.h>28#include <sys/kmem.h>29#include <sys/lock.h>30#include <sys/mutex.h>31#include <sys/queue.h>32#include <sys/taskqueue.h>33#include <sys/taskq.h>3435#include <vm/uma.h>3637static uma_zone_t taskq_zone;3839taskq_t *system_taskq = NULL;4041struct proc *system_proc;4243static void44system_taskq_init(void *arg)45{4647taskq_zone = uma_zcreate("taskq_zone", sizeof(taskq_ent_t),48NULL, NULL, NULL, NULL, 0, 0);49system_taskq = taskq_create("system_taskq", mp_ncpus, minclsyspri,500, 0, 0);51}52SYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL);5354static void55system_taskq_fini(void *arg)56{5758taskq_destroy(system_taskq);59uma_zdestroy(taskq_zone);60}61SYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL);6263static taskq_t *64taskq_create_impl(const char *name, int nthreads, pri_t pri, proc_t *proc,65uint_t flags)66{67taskq_t *tq;6869if ((flags & TASKQ_THREADS_CPU_PCT) != 0)70nthreads = MAX((mp_ncpus * nthreads) / 100, 1);7172tq = kmem_alloc(sizeof(*tq), KM_SLEEP);73tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue,74&tq->tq_queue);75(void) taskqueue_start_threads_in_proc(&tq->tq_queue, nthreads, pri,76proc, "%s", name);7778return ((taskq_t *)tq);79}8081taskq_t *82taskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused,83int maxalloc __unused, uint_t flags)84{85return (taskq_create_impl(name, nthreads, pri, system_proc, flags));86}8788taskq_t *89taskq_create_proc(const char *name, int nthreads, pri_t pri, int minalloc,90int maxalloc, proc_t *proc, uint_t flags)91{92return (taskq_create_impl(name, nthreads, pri, proc, flags));93}9495void96taskq_destroy(taskq_t *tq)97{9899taskqueue_free(tq->tq_queue);100kmem_free(tq, sizeof(*tq));101}102103int104taskq_member(taskq_t *tq, kthread_t *thread)105{106107return (taskqueue_member(tq->tq_queue, thread));108}109110static void111taskq_run(void *arg, int pending __unused)112{113taskq_ent_t *task = arg;114115task->tqent_func(task->tqent_arg);116117uma_zfree(taskq_zone, task);118}119120taskqid_t121taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)122{123taskq_ent_t *task;124int mflag, prio;125126if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP)127mflag = M_WAITOK;128else129mflag = M_NOWAIT;130/*131* If TQ_FRONT is given, we want higher priority for this task, so it132* can go at the front of the queue.133*/134prio = !!(flags & TQ_FRONT);135136task = uma_zalloc(taskq_zone, mflag);137if (task == NULL)138return (0);139140task->tqent_func = func;141task->tqent_arg = arg;142143TASK_INIT(&task->tqent_task, prio, taskq_run, task);144taskqueue_enqueue(tq->tq_queue, &task->tqent_task);145146return ((taskqid_t)(void *)task);147}148149static void150taskq_run_ent(void *arg, int pending __unused)151{152taskq_ent_t *task = arg;153154task->tqent_func(task->tqent_arg);155}156157void158taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, u_int flags,159taskq_ent_t *task)160{161int prio;162163/*164* If TQ_FRONT is given, we want higher priority for this task, so it165* can go at the front of the queue.166*/167prio = !!(flags & TQ_FRONT);168169task->tqent_func = func;170task->tqent_arg = arg;171172TASK_INIT(&task->tqent_task, prio, taskq_run_ent, task);173taskqueue_enqueue(tq->tq_queue, &task->tqent_task);174}175176void177taskq_wait(taskq_t *tq)178{179taskqueue_quiesce(tq->tq_queue);180}181182void183taskq_wait_id(taskq_t *tq, taskqid_t id)184{185taskqueue_drain_all(tq->tq_queue);186}187188189