1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 27 * Copyright (c) 2017 by Delphix. All rights reserved. 28 */ 29 30 #ifndef _SYS_TASKQ_IMPL_H 31 #define _SYS_TASKQ_IMPL_H 32 33 #include <sys/taskq.h> 34 #include <sys/inttypes.h> 35 #include <sys/vmem.h> 36 #include <sys/list.h> 37 #include <sys/kstat.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 typedef struct taskq_bucket taskq_bucket_t; 44 45 typedef struct taskq_ent { 46 struct taskq_ent *tqent_next; 47 struct taskq_ent *tqent_prev; 48 task_func_t *tqent_func; 49 void *tqent_arg; 50 union { 51 taskq_bucket_t *tqent_bucket; 52 uintptr_t tqent_flags; 53 } tqent_un; 54 kthread_t *tqent_thread; 55 kcondvar_t tqent_cv; 56 } taskq_ent_t; 57 58 #define TQENT_FLAG_PREALLOC 0x1 59 60 /* 61 * Taskq Statistics fields are not protected by any locks. 62 */ 63 typedef struct tqstat { 64 uint_t tqs_hits; 65 uint_t tqs_misses; 66 uint_t tqs_overflow; /* no threads to allocate */ 67 uint_t tqs_tcreates; /* threads created */ 68 uint_t tqs_tdeaths; /* threads died */ 69 uint_t tqs_maxthreads; /* max # of alive threads */ 70 uint_t tqs_disptcreates; 71 } tqstat_t; 72 73 /* 74 * Per-CPU hash bucket manages taskq_bent_t structures using freelist. 75 */ 76 struct taskq_bucket { 77 kmutex_t tqbucket_lock; 78 taskq_t *tqbucket_taskq; /* Enclosing taskq */ 79 taskq_ent_t tqbucket_freelist; 80 uint_t tqbucket_nalloc; /* # of allocated entries */ 81 uint_t tqbucket_nfree; /* # of free entries */ 82 kcondvar_t tqbucket_cv; 83 ushort_t tqbucket_flags; 84 hrtime_t tqbucket_totaltime; 85 tqstat_t tqbucket_stat; 86 }; 87 88 /* 89 * Bucket flags. 90 */ 91 #define TQBUCKET_CLOSE 0x01 92 #define TQBUCKET_SUSPEND 0x02 93 94 #define TASKQ_INTERFACE_FLAGS 0x0000ffff /* defined in <sys/taskq.h> */ 95 96 /* 97 * taskq implementation flags: bit range 16-31 98 */ 99 #define TASKQ_CHANGING 0x00010000 /* nthreads != target */ 100 #define TASKQ_SUSPENDED 0x00020000 /* taskq is suspended */ 101 #define TASKQ_NOINSTANCE 0x00040000 /* no instance number */ 102 #define TASKQ_THREAD_CREATED 0x00080000 /* a thread has been created */ 103 #define TASKQ_DUTY_CYCLE 0x00100000 /* using the SDC class */ 104 105 struct taskq { 106 char tq_name[TASKQ_NAMELEN + 1]; 107 kmutex_t tq_lock; 108 krwlock_t tq_threadlock; 109 kcondvar_t tq_dispatch_cv; 110 kcondvar_t tq_wait_cv; 111 kcondvar_t tq_exit_cv; 112 pri_t tq_pri; /* Scheduling priority */ 113 uint_t tq_flags; 114 int tq_active; 115 int tq_nthreads; 116 int tq_nthreads_target; 117 int tq_nthreads_max; 118 int tq_threads_ncpus_pct; 119 int tq_nalloc; 120 int tq_minalloc; 121 int tq_maxalloc; 122 kcondvar_t tq_maxalloc_cv; 123 int tq_maxalloc_wait; 124 taskq_ent_t *tq_freelist; 125 taskq_ent_t tq_task; 126 int tq_maxsize; 127 taskq_bucket_t *tq_buckets; /* Per-cpu array of buckets */ 128 int tq_instance; 129 uint_t tq_nbuckets; /* # of buckets (2^n) */ 130 union { 131 kthread_t *_tq_thread; 132 kthread_t **_tq_threadlist; 133 } tq_thr; 134 135 list_node_t tq_cpupct_link; /* linkage for taskq_cpupct_list */ 136 struct proc *tq_proc; /* process for taskq threads */ 137 int tq_cpupart; /* cpupart id bound to */ 138 uint_t tq_DC; /* duty cycle for SDC */ 139 140 /* 141 * Statistics. 142 */ 143 kstat_t *tq_kstat; /* Exported statistics */ 144 hrtime_t tq_totaltime; /* Time spent processing tasks */ 145 uint64_t tq_nomem; /* # of times there was no memory */ 146 uint64_t tq_tasks; /* Total # of tasks posted */ 147 uint64_t tq_executed; /* Total # of tasks executed */ 148 int tq_maxtasks; /* Max number of tasks in the queue */ 149 int tq_tcreates; 150 int tq_tdeaths; 151 }; 152 153 /* Special form of taskq dispatch that uses preallocated entries. */ 154 void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, taskq_ent_t *); 155 156 157 #define tq_thread tq_thr._tq_thread 158 #define tq_threadlist tq_thr._tq_threadlist 159 160 /* The MAX guarantees we have at least one thread */ 161 #define TASKQ_THREADS_PCT(ncpus, pct) MAX(((ncpus) * (pct)) / 100, 1) 162 163 #ifdef __cplusplus 164 } 165 #endif 166 167 #endif /* _SYS_TASKQ_IMPL_H */