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 * Copyright 2017-2024 RackTop Systems. 29 */ 30 31 #ifndef _SYS_TASKQ_IMPL_H 32 #define _SYS_TASKQ_IMPL_H 33 34 #include <sys/taskq.h> 35 #include <sys/inttypes.h> 36 #include <sys/vmem.h> 37 #include <sys/list.h> 38 #include <sys/kstat.h> 39 #include <sys/rwlock.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 typedef struct taskq_bucket taskq_bucket_t; 46 47 typedef struct taskq_ent { 48 struct taskq_ent *tqent_next; 49 struct taskq_ent *tqent_prev; 50 task_func_t *tqent_func; 51 void *tqent_arg; 52 union { 53 taskq_bucket_t *tqent_bucket; 54 uintptr_t tqent_flags; 55 } tqent_un; 56 kthread_t *tqent_thread; 57 kcondvar_t tqent_cv; 58 } taskq_ent_t; 59 60 #define TQENT_FLAG_PREALLOC 0x1 61 62 /* 63 * Taskq Statistics fields are not protected by any locks. 64 */ 65 typedef struct tqstat { 66 uint64_t tqs_hits; 67 uint64_t tqs_misses; 68 uint64_t tqs_disptcreates; 69 uint64_t tqs_overflow; /* dispatch used backlog */ 70 uint_t tqs_maxbacklog; 71 uint_t tqs_tcreates; /* threads created */ 72 uint_t tqs_tdeaths; /* threads died */ 73 uint_t tqs_maxthreads; /* max # of alive threads */ 74 } tqstat_t; 75 76 /* 77 * Per-CPU hash bucket manages taskq_bent_t structures using freelist. 78 */ 79 struct taskq_bucket { 80 kmutex_t tqbucket_lock; 81 taskq_t *tqbucket_taskq; /* Enclosing taskq */ 82 taskq_ent_t tqbucket_backlog; /* distributed backlog */ 83 taskq_ent_t tqbucket_freelist; 84 uint_t tqbucket_nalloc; /* # of allocated entries */ 85 uint_t tqbucket_nbacklog; /* # of backlog entries */ 86 uint_t tqbucket_nfree; /* # of free entries */ 87 kcondvar_t tqbucket_cv; 88 ushort_t tqbucket_flags; 89 hrtime_t tqbucket_totaltime; 90 tqstat_t tqbucket_stat; 91 }; 92 93 /* 94 * Bucket flags. 95 */ 96 #define TQBUCKET_CLOSE 0x01 97 #define TQBUCKET_SUSPEND 0x02 98 #define TQBUCKET_REDIRECT 0x04 99 100 #define TASKQ_INTERFACE_FLAGS 0x0000ffff /* defined in <sys/taskq.h> */ 101 102 /* 103 * taskq implementation flags: bit range 16-31 104 */ 105 #define TASKQ_CHANGING 0x00010000 /* nthreads != target */ 106 #define TASKQ_SUSPENDED 0x00020000 /* taskq is suspended */ 107 #define TASKQ_NOINSTANCE 0x00040000 /* no instance number */ 108 #define TASKQ_THREAD_CREATED 0x00080000 /* a thread has been created */ 109 #define TASKQ_DUTY_CYCLE 0x00100000 /* using the SDC class */ 110 111 struct taskq { 112 char tq_name[TASKQ_NAMELEN + 1]; 113 kmutex_t tq_lock; 114 krwlock_t tq_threadlock; 115 kcondvar_t tq_dispatch_cv; 116 kcondvar_t tq_wait_cv; 117 kcondvar_t tq_exit_cv; 118 pri_t tq_pri; /* Scheduling priority */ 119 uint_t tq_flags; 120 int tq_active; 121 int tq_nthreads; 122 int tq_nthreads_target; 123 int tq_nthreads_max; 124 int tq_threads_ncpus_pct; 125 int tq_nalloc; 126 int tq_minalloc; 127 int tq_maxalloc; 128 kcondvar_t tq_maxalloc_cv; 129 int tq_maxalloc_wait; 130 taskq_ent_t *tq_freelist; 131 taskq_ent_t tq_task; 132 int tq_maxsize; 133 uint_t tq_atpb; /* avg. thr. per bucket */ 134 taskq_bucket_t *tq_buckets; /* Per-cpu array of buckets */ 135 int tq_instance; 136 uint_t tq_nbuckets; /* # of buckets (2^n) */ 137 union { 138 kthread_t *_tq_thread; 139 kthread_t **_tq_threadlist; 140 } tq_thr; 141 142 list_node_t tq_cpupct_link; /* linkage for taskq_cpupct_list */ 143 struct proc *tq_proc; /* process for taskq threads */ 144 int tq_cpupart; /* cpupart id bound to */ 145 uint_t tq_DC; /* duty cycle for SDC */ 146 147 /* 148 * Statistics. 149 */ 150 kstat_t *tq_kstat; /* Exported statistics */ 151 hrtime_t tq_totaltime; /* Time spent processing tasks */ 152 uint64_t tq_nomem; /* # of times there was no memory */ 153 uint64_t tq_tasks; /* Total # of tasks posted */ 154 uint64_t tq_executed; /* Total # of tasks executed */ 155 int tq_maxtasks; /* Max number of tasks in the queue */ 156 int tq_dnthreads; /* Dynamic N threads */ 157 }; 158 159 /* Special form of taskq dispatch that uses preallocated entries. */ 160 void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, taskq_ent_t *); 161 162 163 #define tq_thread tq_thr._tq_thread 164 #define tq_threadlist tq_thr._tq_threadlist 165 166 /* The MAX guarantees we have at least one thread */ 167 #define TASKQ_THREADS_PCT(ncpus, pct) MAX(((ncpus) * (pct)) / 100, 1) 168 169 #ifdef __cplusplus 170 } 171 #endif 172 173 #endif /* _SYS_TASKQ_IMPL_H */ 174