xref: /illumos-gate/usr/src/uts/common/sys/taskq_impl.h (revision 4224453d626325281f3fcd656e646f681b9eca8b)
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