1b819cea2SGordon Ross /* 2b819cea2SGordon Ross * CDDL HEADER START 3b819cea2SGordon Ross * 4b819cea2SGordon Ross * The contents of this file are subject to the terms of the 5b819cea2SGordon Ross * Common Development and Distribution License (the "License"). 6b819cea2SGordon Ross * You may not use this file except in compliance with the License. 7b819cea2SGordon Ross * 8b819cea2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9b819cea2SGordon Ross * or http://www.opensolaris.org/os/licensing. 10b819cea2SGordon Ross * See the License for the specific language governing permissions 11b819cea2SGordon Ross * and limitations under the License. 12b819cea2SGordon Ross * 13b819cea2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14b819cea2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15b819cea2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16b819cea2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17b819cea2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18b819cea2SGordon Ross * 19b819cea2SGordon Ross * CDDL HEADER END 20b819cea2SGordon Ross */ 21b819cea2SGordon Ross /* 22b819cea2SGordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23b819cea2SGordon Ross * Use is subject to license terms. 24b819cea2SGordon Ross */ 25b819cea2SGordon Ross /* 26b819cea2SGordon Ross * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. 27b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 28f06dce2cSAndrew Stormont * Copyright 2017 RackTop Systems. 294c99ecc3STim Kordas * Copyright 2018, Joyent, Inc. 30b819cea2SGordon Ross */ 31b819cea2SGordon Ross 32b819cea2SGordon Ross #include <sys/taskq_impl.h> 33b819cea2SGordon Ross 34b819cea2SGordon Ross #include <sys/class.h> 35b819cea2SGordon Ross #include <sys/debug.h> 36b819cea2SGordon Ross #include <sys/ksynch.h> 37b819cea2SGordon Ross #include <sys/kmem.h> 38b819cea2SGordon Ross #include <sys/time.h> 39b819cea2SGordon Ross #include <sys/systm.h> 40b819cea2SGordon Ross #include <sys/sysmacros.h> 41b819cea2SGordon Ross #include <sys/unistd.h> 42b819cea2SGordon Ross 43f06dce2cSAndrew Stormont /* avoid <sys/disp.h> */ 44f06dce2cSAndrew Stormont #define maxclsyspri 99 45f06dce2cSAndrew Stormont 46b819cea2SGordon Ross /* avoid <unistd.h> */ 47b819cea2SGordon Ross extern long sysconf(int); 48b819cea2SGordon Ross 49b819cea2SGordon Ross /* avoiding <thread.h> */ 50b819cea2SGordon Ross typedef unsigned int thread_t; 51b819cea2SGordon Ross typedef unsigned int thread_key_t; 52b819cea2SGordon Ross 53b819cea2SGordon Ross extern int thr_create(void *, size_t, void *(*)(void *), void *, long, 54b819cea2SGordon Ross thread_t *); 55b819cea2SGordon Ross extern int thr_join(thread_t, thread_t *, void **); 56b819cea2SGordon Ross 57b819cea2SGordon Ross /* 58b819cea2SGordon Ross * POSIX.1c Note: 59b819cea2SGordon Ross * THR_BOUND is defined same as PTHREAD_SCOPE_SYSTEM in <pthread.h> 60b819cea2SGordon Ross * THR_DETACHED is defined same as PTHREAD_CREATE_DETACHED in <pthread.h> 61b819cea2SGordon Ross * Any changes in these definitions should be reflected in <pthread.h> 62b819cea2SGordon Ross */ 63b819cea2SGordon Ross #define THR_BOUND 0x00000001 /* = PTHREAD_SCOPE_SYSTEM */ 64b819cea2SGordon Ross #define THR_NEW_LWP 0x00000002 65b819cea2SGordon Ross #define THR_DETACHED 0x00000040 /* = PTHREAD_CREATE_DETACHED */ 66b819cea2SGordon Ross #define THR_SUSPENDED 0x00000080 67b819cea2SGordon Ross #define THR_DAEMON 0x00000100 68b819cea2SGordon Ross 69b819cea2SGordon Ross 70b819cea2SGordon Ross int taskq_now; 71b819cea2SGordon Ross taskq_t *system_taskq; 72b819cea2SGordon Ross 73b819cea2SGordon Ross #define TASKQ_ACTIVE 0x00010000 74b819cea2SGordon Ross 75b819cea2SGordon Ross struct taskq { 76b819cea2SGordon Ross kmutex_t tq_lock; 77b819cea2SGordon Ross krwlock_t tq_threadlock; 78b819cea2SGordon Ross kcondvar_t tq_dispatch_cv; 79b819cea2SGordon Ross kcondvar_t tq_wait_cv; 80b819cea2SGordon Ross thread_t *tq_threadlist; 81b819cea2SGordon Ross int tq_flags; 82b819cea2SGordon Ross int tq_active; 83b819cea2SGordon Ross int tq_nthreads; 84b819cea2SGordon Ross int tq_nalloc; 85b819cea2SGordon Ross int tq_minalloc; 86b819cea2SGordon Ross int tq_maxalloc; 87b819cea2SGordon Ross kcondvar_t tq_maxalloc_cv; 88b819cea2SGordon Ross int tq_maxalloc_wait; 89b819cea2SGordon Ross taskq_ent_t *tq_freelist; 90b819cea2SGordon Ross taskq_ent_t tq_task; 91b819cea2SGordon Ross }; 92b819cea2SGordon Ross 93b819cea2SGordon Ross static taskq_ent_t * 94b819cea2SGordon Ross task_alloc(taskq_t *tq, int tqflags) 95b819cea2SGordon Ross { 96b819cea2SGordon Ross taskq_ent_t *t; 97b819cea2SGordon Ross int rv; 98b819cea2SGordon Ross 99b819cea2SGordon Ross again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { 100b819cea2SGordon Ross tq->tq_freelist = t->tqent_next; 101b819cea2SGordon Ross } else { 102b819cea2SGordon Ross if (tq->tq_nalloc >= tq->tq_maxalloc) { 103eda5fc90SJohn Levon if (tqflags & KM_NOSLEEP) 104b819cea2SGordon Ross return (NULL); 105b819cea2SGordon Ross 106b819cea2SGordon Ross /* 107b819cea2SGordon Ross * We don't want to exceed tq_maxalloc, but we can't 108b819cea2SGordon Ross * wait for other tasks to complete (and thus free up 109b819cea2SGordon Ross * task structures) without risking deadlock with 110b819cea2SGordon Ross * the caller. So, we just delay for one second 111b819cea2SGordon Ross * to throttle the allocation rate. If we have tasks 112b819cea2SGordon Ross * complete before one second timeout expires then 113b819cea2SGordon Ross * taskq_ent_free will signal us and we will 114b819cea2SGordon Ross * immediately retry the allocation. 115b819cea2SGordon Ross */ 116b819cea2SGordon Ross tq->tq_maxalloc_wait++; 117b819cea2SGordon Ross rv = cv_timedwait(&tq->tq_maxalloc_cv, 118b819cea2SGordon Ross &tq->tq_lock, ddi_get_lbolt() + hz); 119b819cea2SGordon Ross tq->tq_maxalloc_wait--; 120b819cea2SGordon Ross if (rv > 0) 121b819cea2SGordon Ross goto again; /* signaled */ 122b819cea2SGordon Ross } 123b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 124b819cea2SGordon Ross 125b819cea2SGordon Ross t = kmem_alloc(sizeof (taskq_ent_t), tqflags); 126b819cea2SGordon Ross 127b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 128b819cea2SGordon Ross if (t != NULL) 129b819cea2SGordon Ross tq->tq_nalloc++; 130b819cea2SGordon Ross } 131b819cea2SGordon Ross return (t); 132b819cea2SGordon Ross } 133b819cea2SGordon Ross 134b819cea2SGordon Ross static void 135b819cea2SGordon Ross task_free(taskq_t *tq, taskq_ent_t *t) 136b819cea2SGordon Ross { 137b819cea2SGordon Ross if (tq->tq_nalloc <= tq->tq_minalloc) { 138b819cea2SGordon Ross t->tqent_next = tq->tq_freelist; 139b819cea2SGordon Ross tq->tq_freelist = t; 140b819cea2SGordon Ross } else { 141b819cea2SGordon Ross tq->tq_nalloc--; 142b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 143b819cea2SGordon Ross kmem_free(t, sizeof (taskq_ent_t)); 144b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 145b819cea2SGordon Ross } 146b819cea2SGordon Ross 147b819cea2SGordon Ross if (tq->tq_maxalloc_wait) 148b819cea2SGordon Ross cv_signal(&tq->tq_maxalloc_cv); 149b819cea2SGordon Ross } 150b819cea2SGordon Ross 151b819cea2SGordon Ross taskqid_t 152b819cea2SGordon Ross taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags) 153b819cea2SGordon Ross { 154b819cea2SGordon Ross taskq_ent_t *t; 155b819cea2SGordon Ross 156b819cea2SGordon Ross if (taskq_now) { 157b819cea2SGordon Ross func(arg); 158b819cea2SGordon Ross return (1); 159b819cea2SGordon Ross } 160b819cea2SGordon Ross 161b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 162b819cea2SGordon Ross ASSERT(tq->tq_flags & TASKQ_ACTIVE); 163b819cea2SGordon Ross if ((t = task_alloc(tq, tqflags)) == NULL) { 164b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 165*fc8ae2ecSToomas Soome return (TASKQID_INVALID); 166b819cea2SGordon Ross } 167b819cea2SGordon Ross if (tqflags & TQ_FRONT) { 168b819cea2SGordon Ross t->tqent_next = tq->tq_task.tqent_next; 169b819cea2SGordon Ross t->tqent_prev = &tq->tq_task; 170b819cea2SGordon Ross } else { 171b819cea2SGordon Ross t->tqent_next = &tq->tq_task; 172b819cea2SGordon Ross t->tqent_prev = tq->tq_task.tqent_prev; 173b819cea2SGordon Ross } 174b819cea2SGordon Ross t->tqent_next->tqent_prev = t; 175b819cea2SGordon Ross t->tqent_prev->tqent_next = t; 176b819cea2SGordon Ross t->tqent_func = func; 177b819cea2SGordon Ross t->tqent_arg = arg; 178b819cea2SGordon Ross t->tqent_flags = 0; 179b819cea2SGordon Ross cv_signal(&tq->tq_dispatch_cv); 180b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 181b819cea2SGordon Ross return (1); 182b819cea2SGordon Ross } 183b819cea2SGordon Ross 184b819cea2SGordon Ross void 185b819cea2SGordon Ross taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags, 186b819cea2SGordon Ross taskq_ent_t *t) 187b819cea2SGordon Ross { 188b819cea2SGordon Ross ASSERT(func != NULL); 189b819cea2SGordon Ross ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC)); 190b819cea2SGordon Ross 191b819cea2SGordon Ross /* 192b819cea2SGordon Ross * Mark it as a prealloc'd task. This is important 193b819cea2SGordon Ross * to ensure that we don't free it later. 194b819cea2SGordon Ross */ 195b819cea2SGordon Ross t->tqent_flags |= TQENT_FLAG_PREALLOC; 196b819cea2SGordon Ross /* 197b819cea2SGordon Ross * Enqueue the task to the underlying queue. 198b819cea2SGordon Ross */ 199b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 200b819cea2SGordon Ross 201b819cea2SGordon Ross if (flags & TQ_FRONT) { 202b819cea2SGordon Ross t->tqent_next = tq->tq_task.tqent_next; 203b819cea2SGordon Ross t->tqent_prev = &tq->tq_task; 204b819cea2SGordon Ross } else { 205b819cea2SGordon Ross t->tqent_next = &tq->tq_task; 206b819cea2SGordon Ross t->tqent_prev = tq->tq_task.tqent_prev; 207b819cea2SGordon Ross } 208b819cea2SGordon Ross t->tqent_next->tqent_prev = t; 209b819cea2SGordon Ross t->tqent_prev->tqent_next = t; 210b819cea2SGordon Ross t->tqent_func = func; 211b819cea2SGordon Ross t->tqent_arg = arg; 212b819cea2SGordon Ross cv_signal(&tq->tq_dispatch_cv); 213b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 214b819cea2SGordon Ross } 215b819cea2SGordon Ross 2164c99ecc3STim Kordas boolean_t 2174c99ecc3STim Kordas taskq_empty(taskq_t *tq) 2184c99ecc3STim Kordas { 2194c99ecc3STim Kordas boolean_t rv; 2204c99ecc3STim Kordas 2214c99ecc3STim Kordas mutex_enter(&tq->tq_lock); 2224c99ecc3STim Kordas rv = (tq->tq_task.tqent_next == &tq->tq_task) && (tq->tq_active == 0); 2234c99ecc3STim Kordas mutex_exit(&tq->tq_lock); 2244c99ecc3STim Kordas 2254c99ecc3STim Kordas return (rv); 2264c99ecc3STim Kordas } 2274c99ecc3STim Kordas 228b819cea2SGordon Ross void 229b819cea2SGordon Ross taskq_wait(taskq_t *tq) 230b819cea2SGordon Ross { 231b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 232b819cea2SGordon Ross while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0) 233b819cea2SGordon Ross cv_wait(&tq->tq_wait_cv, &tq->tq_lock); 234b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 235b819cea2SGordon Ross } 236b819cea2SGordon Ross 237b819cea2SGordon Ross static void * 238b819cea2SGordon Ross taskq_thread(void *arg) 239b819cea2SGordon Ross { 240b819cea2SGordon Ross taskq_t *tq = arg; 241b819cea2SGordon Ross taskq_ent_t *t; 242b819cea2SGordon Ross boolean_t prealloc; 243b819cea2SGordon Ross 244b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 245b819cea2SGordon Ross while (tq->tq_flags & TASKQ_ACTIVE) { 246b819cea2SGordon Ross if ((t = tq->tq_task.tqent_next) == &tq->tq_task) { 247b819cea2SGordon Ross if (--tq->tq_active == 0) 248b819cea2SGordon Ross cv_broadcast(&tq->tq_wait_cv); 249b819cea2SGordon Ross cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock); 250b819cea2SGordon Ross tq->tq_active++; 251b819cea2SGordon Ross continue; 252b819cea2SGordon Ross } 253b819cea2SGordon Ross t->tqent_prev->tqent_next = t->tqent_next; 254b819cea2SGordon Ross t->tqent_next->tqent_prev = t->tqent_prev; 255b819cea2SGordon Ross t->tqent_next = NULL; 256b819cea2SGordon Ross t->tqent_prev = NULL; 257b819cea2SGordon Ross prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC; 258b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 259b819cea2SGordon Ross 260b819cea2SGordon Ross rw_enter(&tq->tq_threadlock, RW_READER); 261b819cea2SGordon Ross t->tqent_func(t->tqent_arg); 262b819cea2SGordon Ross rw_exit(&tq->tq_threadlock); 263b819cea2SGordon Ross 264b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 265b819cea2SGordon Ross if (!prealloc) 266b819cea2SGordon Ross task_free(tq, t); 267b819cea2SGordon Ross } 268b819cea2SGordon Ross tq->tq_nthreads--; 269b819cea2SGordon Ross cv_broadcast(&tq->tq_wait_cv); 270b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 271b819cea2SGordon Ross return (NULL); 272b819cea2SGordon Ross } 273b819cea2SGordon Ross 274b819cea2SGordon Ross /*ARGSUSED*/ 275b819cea2SGordon Ross taskq_t * 276b819cea2SGordon Ross taskq_create(const char *name, int nthr, pri_t pri, int minalloc, 277b819cea2SGordon Ross int maxalloc, uint_t flags) 278b819cea2SGordon Ross { 279b819cea2SGordon Ross return (taskq_create_proc(name, nthr, pri, 280b819cea2SGordon Ross minalloc, maxalloc, NULL, flags)); 281b819cea2SGordon Ross } 282b819cea2SGordon Ross 283f06dce2cSAndrew Stormont /*ARGSUSED*/ 284f06dce2cSAndrew Stormont taskq_t * 285f06dce2cSAndrew Stormont taskq_create_sysdc(const char *name, int nthr, int minalloc, 286f06dce2cSAndrew Stormont int maxalloc, proc_t *proc, uint_t dc, uint_t flags) 287f06dce2cSAndrew Stormont { 288f06dce2cSAndrew Stormont return (taskq_create_proc(name, nthr, maxclsyspri, 289f06dce2cSAndrew Stormont minalloc, maxalloc, proc, flags)); 290f06dce2cSAndrew Stormont } 291f06dce2cSAndrew Stormont 292b819cea2SGordon Ross /*ARGSUSED*/ 293b819cea2SGordon Ross taskq_t * 294b819cea2SGordon Ross taskq_create_proc(const char *name, int nthreads, pri_t pri, 295f06dce2cSAndrew Stormont int minalloc, int maxalloc, proc_t *proc, uint_t flags) 296b819cea2SGordon Ross { 297b819cea2SGordon Ross taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP); 298b819cea2SGordon Ross int t; 299b819cea2SGordon Ross 300b819cea2SGordon Ross if (flags & TASKQ_THREADS_CPU_PCT) { 301b819cea2SGordon Ross int pct; 302b819cea2SGordon Ross ASSERT3S(nthreads, >=, 0); 303b819cea2SGordon Ross ASSERT3S(nthreads, <=, 100); 304b819cea2SGordon Ross pct = MIN(nthreads, 100); 305b819cea2SGordon Ross pct = MAX(pct, 0); 306b819cea2SGordon Ross 307b819cea2SGordon Ross nthreads = (sysconf(_SC_NPROCESSORS_ONLN) * pct) / 100; 308b819cea2SGordon Ross nthreads = MAX(nthreads, 1); /* need at least 1 thread */ 309b819cea2SGordon Ross } else { 310b819cea2SGordon Ross ASSERT3S(nthreads, >=, 1); 311b819cea2SGordon Ross } 312b819cea2SGordon Ross 313b819cea2SGordon Ross rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL); 314b819cea2SGordon Ross mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL); 315b819cea2SGordon Ross cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL); 316b819cea2SGordon Ross cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL); 317b819cea2SGordon Ross cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL); 318b819cea2SGordon Ross tq->tq_flags = flags | TASKQ_ACTIVE; 319b819cea2SGordon Ross tq->tq_active = nthreads; 320b819cea2SGordon Ross tq->tq_nthreads = nthreads; 321b819cea2SGordon Ross tq->tq_minalloc = minalloc; 322b819cea2SGordon Ross tq->tq_maxalloc = maxalloc; 323b819cea2SGordon Ross tq->tq_task.tqent_next = &tq->tq_task; 324b819cea2SGordon Ross tq->tq_task.tqent_prev = &tq->tq_task; 325b819cea2SGordon Ross tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP); 326b819cea2SGordon Ross 327b819cea2SGordon Ross if (flags & TASKQ_PREPOPULATE) { 328b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 329b819cea2SGordon Ross while (minalloc-- > 0) 330b819cea2SGordon Ross task_free(tq, task_alloc(tq, KM_SLEEP)); 331b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 332b819cea2SGordon Ross } 333b819cea2SGordon Ross 334b819cea2SGordon Ross for (t = 0; t < nthreads; t++) 335b819cea2SGordon Ross (void) thr_create(0, 0, taskq_thread, 336b819cea2SGordon Ross tq, THR_BOUND, &tq->tq_threadlist[t]); 337b819cea2SGordon Ross 338b819cea2SGordon Ross return (tq); 339b819cea2SGordon Ross } 340b819cea2SGordon Ross 341b819cea2SGordon Ross void 342b819cea2SGordon Ross taskq_destroy(taskq_t *tq) 343b819cea2SGordon Ross { 344b819cea2SGordon Ross int t; 345b819cea2SGordon Ross int nthreads = tq->tq_nthreads; 346b819cea2SGordon Ross 347b819cea2SGordon Ross taskq_wait(tq); 348b819cea2SGordon Ross 349b819cea2SGordon Ross mutex_enter(&tq->tq_lock); 350b819cea2SGordon Ross 351b819cea2SGordon Ross tq->tq_flags &= ~TASKQ_ACTIVE; 352b819cea2SGordon Ross cv_broadcast(&tq->tq_dispatch_cv); 353b819cea2SGordon Ross 354b819cea2SGordon Ross while (tq->tq_nthreads != 0) 355b819cea2SGordon Ross cv_wait(&tq->tq_wait_cv, &tq->tq_lock); 356b819cea2SGordon Ross 357b819cea2SGordon Ross tq->tq_minalloc = 0; 358b819cea2SGordon Ross while (tq->tq_nalloc != 0) { 359b819cea2SGordon Ross ASSERT(tq->tq_freelist != NULL); 360b819cea2SGordon Ross task_free(tq, task_alloc(tq, KM_SLEEP)); 361b819cea2SGordon Ross } 362b819cea2SGordon Ross 363b819cea2SGordon Ross mutex_exit(&tq->tq_lock); 364b819cea2SGordon Ross 365b819cea2SGordon Ross for (t = 0; t < nthreads; t++) 366b819cea2SGordon Ross (void) thr_join(tq->tq_threadlist[t], NULL, NULL); 367b819cea2SGordon Ross 368b819cea2SGordon Ross kmem_free(tq->tq_threadlist, nthreads * sizeof (thread_t)); 369b819cea2SGordon Ross 370b819cea2SGordon Ross rw_destroy(&tq->tq_threadlock); 371b819cea2SGordon Ross mutex_destroy(&tq->tq_lock); 372b819cea2SGordon Ross cv_destroy(&tq->tq_dispatch_cv); 373b819cea2SGordon Ross cv_destroy(&tq->tq_wait_cv); 374b819cea2SGordon Ross cv_destroy(&tq->tq_maxalloc_cv); 375b819cea2SGordon Ross 376b819cea2SGordon Ross kmem_free(tq, sizeof (taskq_t)); 377b819cea2SGordon Ross } 378b819cea2SGordon Ross 379b819cea2SGordon Ross int 380b819cea2SGordon Ross taskq_member(taskq_t *tq, struct _kthread *t) 381b819cea2SGordon Ross { 382b819cea2SGordon Ross int i; 383b819cea2SGordon Ross 384b819cea2SGordon Ross if (taskq_now) 385b819cea2SGordon Ross return (1); 386b819cea2SGordon Ross 387b819cea2SGordon Ross for (i = 0; i < tq->tq_nthreads; i++) 388b819cea2SGordon Ross if (tq->tq_threadlist[i] == (thread_t)(uintptr_t)t) 389b819cea2SGordon Ross return (1); 390b819cea2SGordon Ross 391b819cea2SGordon Ross return (0); 392b819cea2SGordon Ross } 393b819cea2SGordon Ross 394b819cea2SGordon Ross void 395b819cea2SGordon Ross system_taskq_init(void) 396b819cea2SGordon Ross { 397b819cea2SGordon Ross system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512, 398b819cea2SGordon Ross TASKQ_DYNAMIC | TASKQ_PREPOPULATE); 399b819cea2SGordon Ross } 400b819cea2SGordon Ross 401b819cea2SGordon Ross void 402b819cea2SGordon Ross system_taskq_fini(void) 403b819cea2SGordon Ross { 404b819cea2SGordon Ross taskq_destroy(system_taskq); 405b819cea2SGordon Ross system_taskq = NULL; /* defensive */ 406b819cea2SGordon Ross } 407