author | Garrett D'Amore <garrett@nexenta.com> |
Wed, 27 Jul 2011 07:13:44 -0700 | |
changeset 13414 | b42c1f0432b6 |
parent 11854 | 5351ddd19d45 |
permissions | -rw-r--r-- |
0 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
5 |
* Common Development and Distribution License (the "License"). |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
6 |
* You may not use this file except in compliance with the License. |
0 | 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 |
/* |
|
11474
857f9db4ef05
4517853 debug.h should include macros to assert implication and equivalence
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11173
diff
changeset
|
22 |
* Copyright 2010 Sun Microsystems, Inc. All rights reserved. |
0 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
26 |
/* |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
27 |
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
28 |
*/ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
29 |
|
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
30 |
/* |
0 | 31 |
* Kernel task queues: general-purpose asynchronous task scheduling. |
32 |
* |
|
33 |
* A common problem in kernel programming is the need to schedule tasks |
|
34 |
* to be performed later, by another thread. There are several reasons |
|
35 |
* you may want or need to do this: |
|
36 |
* |
|
37 |
* (1) The task isn't time-critical, but your current code path is. |
|
38 |
* |
|
39 |
* (2) The task may require grabbing locks that you already hold. |
|
40 |
* |
|
41 |
* (3) The task may need to block (e.g. to wait for memory), but you |
|
42 |
* cannot block in your current context. |
|
43 |
* |
|
44 |
* (4) Your code path can't complete because of some condition, but you can't |
|
45 |
* sleep or fail, so you queue the task for later execution when condition |
|
46 |
* disappears. |
|
47 |
* |
|
48 |
* (5) You just want a simple way to launch multiple tasks in parallel. |
|
49 |
* |
|
50 |
* Task queues provide such a facility. In its simplest form (used when |
|
51 |
* performance is not a critical consideration) a task queue consists of a |
|
52 |
* single list of tasks, together with one or more threads to service the |
|
53 |
* list. There are some cases when this simple queue is not sufficient: |
|
54 |
* |
|
55 |
* (1) The task queues are very hot and there is a need to avoid data and lock |
|
56 |
* contention over global resources. |
|
57 |
* |
|
58 |
* (2) Some tasks may depend on other tasks to complete, so they can't be put in |
|
59 |
* the same list managed by the same thread. |
|
60 |
* |
|
61 |
* (3) Some tasks may block for a long time, and this should not block other |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
62 |
* tasks in the queue. |
0 | 63 |
* |
64 |
* To provide useful service in such cases we define a "dynamic task queue" |
|
65 |
* which has an individual thread for each of the tasks. These threads are |
|
66 |
* dynamically created as they are needed and destroyed when they are not in |
|
67 |
* use. The API for managing task pools is the same as for managing task queues |
|
68 |
* with the exception of a taskq creation flag TASKQ_DYNAMIC which tells that |
|
69 |
* dynamic task pool behavior is desired. |
|
70 |
* |
|
71 |
* Dynamic task queues may also place tasks in the normal queue (called "backing |
|
72 |
* queue") when task pool runs out of resources. Users of task queues may |
|
73 |
* disallow such queued scheduling by specifying TQ_NOQUEUE in the dispatch |
|
74 |
* flags. |
|
75 |
* |
|
76 |
* The backing task queue is also used for scheduling internal tasks needed for |
|
77 |
* dynamic task queue maintenance. |
|
78 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
79 |
* INTERFACES ================================================================== |
0 | 80 |
* |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
81 |
* taskq_t *taskq_create(name, nthreads, pri, minalloc, maxall, flags); |
0 | 82 |
* |
83 |
* Create a taskq with specified properties. |
|
84 |
* Possible 'flags': |
|
85 |
* |
|
86 |
* TASKQ_DYNAMIC: Create task pool for task management. If this flag is |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
87 |
* specified, 'nthreads' specifies the maximum number of threads in |
0 | 88 |
* the task queue. Task execution order for dynamic task queues is |
89 |
* not predictable. |
|
90 |
* |
|
91 |
* If this flag is not specified (default case) a |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
92 |
* single-list task queue is created with 'nthreads' threads |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
93 |
* servicing it. Entries in this queue are managed by |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
94 |
* taskq_ent_alloc() and taskq_ent_free() which try to keep the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
95 |
* task population between 'minalloc' and 'maxalloc', but the |
0 | 96 |
* latter limit is only advisory for TQ_SLEEP dispatches and the |
97 |
* former limit is only advisory for TQ_NOALLOC dispatches. If |
|
98 |
* TASKQ_PREPOPULATE is set in 'flags', the taskq will be |
|
99 |
* prepopulated with 'minalloc' task structures. |
|
100 |
* |
|
101 |
* Since non-DYNAMIC taskqs are queues, tasks are guaranteed to be |
|
102 |
* executed in the order they are scheduled if nthreads == 1. |
|
103 |
* If nthreads > 1, task execution order is not predictable. |
|
104 |
* |
|
105 |
* TASKQ_PREPOPULATE: Prepopulate task queue with threads. |
|
106 |
* Also prepopulate the task queue with 'minalloc' task structures. |
|
107 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
108 |
* TASKQ_THREADS_CPU_PCT: This flag specifies that 'nthreads' should be |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
109 |
* interpreted as a percentage of the # of online CPUs on the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
110 |
* system. The taskq subsystem will automatically adjust the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
111 |
* number of threads in the taskq in response to CPU online |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
112 |
* and offline events, to keep the ratio. nthreads must be in |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
113 |
* the range [0,100]. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
114 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
115 |
* The calculation used is: |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
116 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
117 |
* MAX((ncpus_online * percentage)/100, 1) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
118 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
119 |
* This flag is not supported for DYNAMIC task queues. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
120 |
* This flag is not compatible with TASKQ_CPR_SAFE. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
121 |
* |
0 | 122 |
* TASKQ_CPR_SAFE: This flag specifies that users of the task queue will |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
123 |
* use their own protocol for handling CPR issues. This flag is not |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
124 |
* supported for DYNAMIC task queues. This flag is not compatible |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
125 |
* with TASKQ_THREADS_CPU_PCT. |
0 | 126 |
* |
127 |
* The 'pri' field specifies the default priority for the threads that |
|
128 |
* service all scheduled tasks. |
|
129 |
* |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
130 |
* taskq_t *taskq_create_instance(name, instance, nthreads, pri, minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
131 |
* maxall, flags); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
132 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
133 |
* Like taskq_create(), but takes an instance number (or -1 to indicate |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
134 |
* no instance). |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
135 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
136 |
* taskq_t *taskq_create_proc(name, nthreads, pri, minalloc, maxall, proc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
137 |
* flags); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
138 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
139 |
* Like taskq_create(), but creates the taskq threads in the specified |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
140 |
* system process. If proc != &p0, this must be called from a thread |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
141 |
* in that process. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
142 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
143 |
* taskq_t *taskq_create_sysdc(name, nthreads, minalloc, maxall, proc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
144 |
* dc, flags); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
145 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
146 |
* Like taskq_create_proc(), but the taskq threads will use the |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
147 |
* System Duty Cycle (SDC) scheduling class with a duty cycle of dc. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
148 |
* |
0 | 149 |
* void taskq_destroy(tap): |
150 |
* |
|
151 |
* Waits for any scheduled tasks to complete, then destroys the taskq. |
|
152 |
* Caller should guarantee that no new tasks are scheduled in the closing |
|
153 |
* taskq. |
|
154 |
* |
|
155 |
* taskqid_t taskq_dispatch(tq, func, arg, flags): |
|
156 |
* |
|
157 |
* Dispatches the task "func(arg)" to taskq. The 'flags' indicates whether |
|
158 |
* the caller is willing to block for memory. The function returns an |
|
159 |
* opaque value which is zero iff dispatch fails. If flags is TQ_NOSLEEP |
|
160 |
* or TQ_NOALLOC and the task can't be dispatched, taskq_dispatch() fails |
|
161 |
* and returns (taskqid_t)0. |
|
162 |
* |
|
163 |
* ASSUMES: func != NULL. |
|
164 |
* |
|
165 |
* Possible flags: |
|
166 |
* TQ_NOSLEEP: Do not wait for resources; may fail. |
|
167 |
* |
|
168 |
* TQ_NOALLOC: Do not allocate memory; may fail. May only be used with |
|
169 |
* non-dynamic task queues. |
|
170 |
* |
|
171 |
* TQ_NOQUEUE: Do not enqueue a task if it can't dispatch it due to |
|
172 |
* lack of available resources and fail. If this flag is not |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
173 |
* set, and the task pool is exhausted, the task may be scheduled |
0 | 174 |
* in the backing queue. This flag may ONLY be used with dynamic |
175 |
* task queues. |
|
176 |
* |
|
177 |
* NOTE: This flag should always be used when a task queue is used |
|
178 |
* for tasks that may depend on each other for completion. |
|
179 |
* Enqueueing dependent tasks may create deadlocks. |
|
180 |
* |
|
181 |
* TQ_SLEEP: May block waiting for resources. May still fail for |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
182 |
* dynamic task queues if TQ_NOQUEUE is also specified, otherwise |
0 | 183 |
* always succeed. |
184 |
* |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
185 |
* TQ_FRONT: Puts the new task at the front of the queue. Be careful. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
186 |
* |
0 | 187 |
* NOTE: Dynamic task queues are much more likely to fail in |
188 |
* taskq_dispatch() (especially if TQ_NOQUEUE was specified), so it |
|
189 |
* is important to have backup strategies handling such failures. |
|
190 |
* |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
191 |
* void taskq_dispatch_ent(tq, func, arg, flags, tqent) |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
192 |
* |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
193 |
* This is a light-weight form of taskq_dispatch(), that uses a |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
194 |
* preallocated taskq_ent_t structure for scheduling. As a |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
195 |
* result, it does not perform allocations and cannot ever fail. |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
196 |
* Note especially that it cannot be used with TASKQ_DYNAMIC |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
197 |
* taskqs. The memory for the tqent must not be modified or used |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
198 |
* until the function (func) is called. (However, func itself |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
199 |
* may safely modify or free this memory, once it is called.) |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
200 |
* Note that the taskq framework will NOT free this memory. |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
201 |
* |
0 | 202 |
* void taskq_wait(tq): |
203 |
* |
|
204 |
* Waits for all previously scheduled tasks to complete. |
|
205 |
* |
|
206 |
* NOTE: It does not stop any new task dispatches. |
|
207 |
* Do NOT call taskq_wait() from a task: it will cause deadlock. |
|
208 |
* |
|
209 |
* void taskq_suspend(tq) |
|
210 |
* |
|
211 |
* Suspend all task execution. Tasks already scheduled for a dynamic task |
|
212 |
* queue will still be executed, but all new scheduled tasks will be |
|
213 |
* suspended until taskq_resume() is called. |
|
214 |
* |
|
215 |
* int taskq_suspended(tq) |
|
216 |
* |
|
217 |
* Returns 1 if taskq is suspended and 0 otherwise. It is intended to |
|
218 |
* ASSERT that the task queue is suspended. |
|
219 |
* |
|
220 |
* void taskq_resume(tq) |
|
221 |
* |
|
222 |
* Resume task queue execution. |
|
223 |
* |
|
224 |
* int taskq_member(tq, thread) |
|
225 |
* |
|
226 |
* Returns 1 if 'thread' belongs to taskq 'tq' and 0 otherwise. The |
|
227 |
* intended use is to ASSERT that a given function is called in taskq |
|
228 |
* context only. |
|
229 |
* |
|
230 |
* system_taskq |
|
231 |
* |
|
232 |
* Global system-wide dynamic task queue for common uses. It may be used by |
|
233 |
* any subsystem that needs to schedule tasks and does not need to manage |
|
234 |
* its own task queues. It is initialized quite early during system boot. |
|
235 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
236 |
* IMPLEMENTATION ============================================================== |
0 | 237 |
* |
238 |
* This is schematic representation of the task queue structures. |
|
239 |
* |
|
240 |
* taskq: |
|
241 |
* +-------------+ |
|
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
242 |
* | tq_lock | +---< taskq_ent_free() |
0 | 243 |
* +-------------+ | |
244 |
* |... | | tqent: tqent: |
|
245 |
* +-------------+ | +------------+ +------------+ |
|
246 |
* | tq_freelist |-->| tqent_next |--> ... ->| tqent_next | |
|
247 |
* +-------------+ +------------+ +------------+ |
|
248 |
* |... | | ... | | ... | |
|
249 |
* +-------------+ +------------+ +------------+ |
|
250 |
* | tq_task | | |
|
251 |
* | | +-------------->taskq_ent_alloc() |
|
252 |
* +--------------------------------------------------------------------------+ |
|
253 |
* | | | tqent tqent | |
|
254 |
* | +---------------------+ +--> +------------+ +--> +------------+ | |
|
255 |
* | | ... | | | func, arg | | | func, arg | | |
|
256 |
* +>+---------------------+ <---|-+ +------------+ <---|-+ +------------+ | |
|
257 |
* | tq_taskq.tqent_next | ----+ | | tqent_next | --->+ | | tqent_next |--+ |
|
258 |
* +---------------------+ | +------------+ ^ | +------------+ |
|
259 |
* +-| tq_task.tqent_prev | +--| tqent_prev | | +--| tqent_prev | ^ |
|
260 |
* | +---------------------+ +------------+ | +------------+ | |
|
261 |
* | |... | | ... | | | ... | | |
|
262 |
* | +---------------------+ +------------+ | +------------+ | |
|
263 |
* | ^ | | |
|
264 |
* | | | | |
|
265 |
* +--------------------------------------+--------------+ TQ_APPEND() -+ |
|
266 |
* | | | |
|
267 |
* |... | taskq_thread()-----+ |
|
268 |
* +-------------+ |
|
269 |
* | tq_buckets |--+-------> [ NULL ] (for regular task queues) |
|
270 |
* +-------------+ | |
|
271 |
* | DYNAMIC TASK QUEUES: |
|
272 |
* | |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
273 |
* +-> taskq_bucket[nCPU] taskq_bucket_dispatch() |
0 | 274 |
* +-------------------+ ^ |
275 |
* +--->| tqbucket_lock | | |
|
276 |
* | +-------------------+ +--------+ +--------+ |
|
277 |
* | | tqbucket_freelist |-->| tqent |-->...| tqent | ^ |
|
278 |
* | +-------------------+<--+--------+<--...+--------+ | |
|
279 |
* | | ... | | thread | | thread | | |
|
280 |
* | +-------------------+ +--------+ +--------+ | |
|
281 |
* | +-------------------+ | |
|
282 |
* taskq_dispatch()--+--->| tqbucket_lock | TQ_APPEND()------+ |
|
283 |
* TQ_HASH() | +-------------------+ +--------+ +--------+ |
|
284 |
* | | tqbucket_freelist |-->| tqent |-->...| tqent | |
|
285 |
* | +-------------------+<--+--------+<--...+--------+ |
|
286 |
* | | ... | | thread | | thread | |
|
287 |
* | +-------------------+ +--------+ +--------+ |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
288 |
* +---> ... |
0 | 289 |
* |
290 |
* |
|
291 |
* Task queues use tq_task field to link new entry in the queue. The queue is a |
|
292 |
* circular doubly-linked list. Entries are put in the end of the list with |
|
293 |
* TQ_APPEND() and processed from the front of the list by taskq_thread() in |
|
294 |
* FIFO order. Task queue entries are cached in the free list managed by |
|
295 |
* taskq_ent_alloc() and taskq_ent_free() functions. |
|
296 |
* |
|
297 |
* All threads used by task queues mark t_taskq field of the thread to |
|
298 |
* point to the task queue. |
|
299 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
300 |
* Taskq Thread Management ----------------------------------------------------- |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
301 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
302 |
* Taskq's non-dynamic threads are managed with several variables and flags: |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
303 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
304 |
* * tq_nthreads - The number of threads in taskq_thread() for the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
305 |
* taskq. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
306 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
307 |
* * tq_active - The number of threads not waiting on a CV in |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
308 |
* taskq_thread(); includes newly created threads |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
309 |
* not yet counted in tq_nthreads. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
310 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
311 |
* * tq_nthreads_target |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
312 |
* - The number of threads desired for the taskq. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
313 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
314 |
* * tq_flags & TASKQ_CHANGING |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
315 |
* - Indicates that tq_nthreads != tq_nthreads_target. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
316 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
317 |
* * tq_flags & TASKQ_THREAD_CREATED |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
318 |
* - Indicates that a thread is being created in the taskq. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
319 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
320 |
* During creation, tq_nthreads and tq_active are set to 0, and |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
321 |
* tq_nthreads_target is set to the number of threads desired. The |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
322 |
* TASKQ_CHANGING flag is set, and taskq_thread_create() is called to |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
323 |
* create the first thread. taskq_thread_create() increments tq_active, |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
324 |
* sets TASKQ_THREAD_CREATED, and creates the new thread. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
325 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
326 |
* Each thread starts in taskq_thread(), clears the TASKQ_THREAD_CREATED |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
327 |
* flag, and increments tq_nthreads. It stores the new value of |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
328 |
* tq_nthreads as its "thread_id", and stores its thread pointer in the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
329 |
* tq_threadlist at the (thread_id - 1). We keep the thread_id space |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
330 |
* densely packed by requiring that only the largest thread_id can exit during |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
331 |
* normal adjustment. The exception is during the destruction of the |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
332 |
* taskq; once tq_nthreads_target is set to zero, no new threads will be created |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
333 |
* for the taskq queue, so every thread can exit without any ordering being |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
334 |
* necessary. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
335 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
336 |
* Threads will only process work if their thread id is <= tq_nthreads_target. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
337 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
338 |
* When TASKQ_CHANGING is set, threads will check the current thread target |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
339 |
* whenever they wake up, and do whatever they can to apply its effects. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
340 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
341 |
* TASKQ_THREAD_CPU_PCT -------------------------------------------------------- |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
342 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
343 |
* When a taskq is created with TASKQ_THREAD_CPU_PCT, we store their requested |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
344 |
* percentage in tq_threads_ncpus_pct, start them off with the correct thread |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
345 |
* target, and add them to the taskq_cpupct_list for later adjustment. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
346 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
347 |
* We register taskq_cpu_setup() to be called whenever a CPU changes state. It |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
348 |
* walks the list of TASKQ_THREAD_CPU_PCT taskqs, adjusts their nthread_target |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
349 |
* if need be, and wakes up all of the threads to process the change. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
350 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
351 |
* Dynamic Task Queues Implementation ------------------------------------------ |
0 | 352 |
* |
353 |
* For a dynamic task queues there is a 1-to-1 mapping between a thread and |
|
354 |
* taskq_ent_structure. Each entry is serviced by its own thread and each thread |
|
355 |
* is controlled by a single entry. |
|
356 |
* |
|
357 |
* Entries are distributed over a set of buckets. To avoid using modulo |
|
358 |
* arithmetics the number of buckets is 2^n and is determined as the nearest |
|
359 |
* power of two roundown of the number of CPUs in the system. Tunable |
|
360 |
* variable 'taskq_maxbuckets' limits the maximum number of buckets. Each entry |
|
361 |
* is attached to a bucket for its lifetime and can't migrate to other buckets. |
|
362 |
* |
|
363 |
* Entries that have scheduled tasks are not placed in any list. The dispatch |
|
364 |
* function sets their "func" and "arg" fields and signals the corresponding |
|
365 |
* thread to execute the task. Once the thread executes the task it clears the |
|
366 |
* "func" field and places an entry on the bucket cache of free entries pointed |
|
367 |
* by "tqbucket_freelist" field. ALL entries on the free list should have "func" |
|
368 |
* field equal to NULL. The free list is a circular doubly-linked list identical |
|
369 |
* in structure to the tq_task list above, but entries are taken from it in LIFO |
|
370 |
* order - the last freed entry is the first to be allocated. The |
|
371 |
* taskq_bucket_dispatch() function gets the most recently used entry from the |
|
372 |
* free list, sets its "func" and "arg" fields and signals a worker thread. |
|
373 |
* |
|
374 |
* After executing each task a per-entry thread taskq_d_thread() places its |
|
375 |
* entry on the bucket free list and goes to a timed sleep. If it wakes up |
|
376 |
* without getting new task it removes the entry from the free list and destroys |
|
377 |
* itself. The thread sleep time is controlled by a tunable variable |
|
378 |
* `taskq_thread_timeout'. |
|
379 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
380 |
* There are various statistics kept in the bucket which allows for later |
0 | 381 |
* analysis of taskq usage patterns. Also, a global copy of taskq creation and |
382 |
* death statistics is kept in the global taskq data structure. Since thread |
|
383 |
* creation and death happen rarely, updating such global data does not present |
|
384 |
* a performance problem. |
|
385 |
* |
|
386 |
* NOTE: Threads are not bound to any CPU and there is absolutely no association |
|
387 |
* between the bucket and actual thread CPU, so buckets are used only to |
|
388 |
* split resources and reduce resource contention. Having threads attached |
|
389 |
* to the CPU denoted by a bucket may reduce number of times the job |
|
390 |
* switches between CPUs. |
|
391 |
* |
|
392 |
* Current algorithm creates a thread whenever a bucket has no free |
|
393 |
* entries. It would be nice to know how many threads are in the running |
|
394 |
* state and don't create threads if all CPUs are busy with existing |
|
395 |
* tasks, but it is unclear how such strategy can be implemented. |
|
396 |
* |
|
397 |
* Currently buckets are created statically as an array attached to task |
|
398 |
* queue. On some system with nCPUs < max_ncpus it may waste system |
|
399 |
* memory. One solution may be allocation of buckets when they are first |
|
400 |
* touched, but it is not clear how useful it is. |
|
401 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
402 |
* SUSPEND/RESUME implementation ----------------------------------------------- |
0 | 403 |
* |
404 |
* Before executing a task taskq_thread() (executing non-dynamic task |
|
405 |
* queues) obtains taskq's thread lock as a reader. The taskq_suspend() |
|
406 |
* function gets the same lock as a writer blocking all non-dynamic task |
|
407 |
* execution. The taskq_resume() function releases the lock allowing |
|
408 |
* taskq_thread to continue execution. |
|
409 |
* |
|
410 |
* For dynamic task queues, each bucket is marked as TQBUCKET_SUSPEND by |
|
411 |
* taskq_suspend() function. After that taskq_bucket_dispatch() always |
|
412 |
* fails, so that taskq_dispatch() will either enqueue tasks for a |
|
413 |
* suspended backing queue or fail if TQ_NOQUEUE is specified in dispatch |
|
414 |
* flags. |
|
415 |
* |
|
416 |
* NOTE: taskq_suspend() does not immediately block any tasks already |
|
417 |
* scheduled for dynamic task queues. It only suspends new tasks |
|
418 |
* scheduled after taskq_suspend() was called. |
|
419 |
* |
|
420 |
* taskq_member() function works by comparing a thread t_taskq pointer with |
|
421 |
* the passed thread pointer. |
|
422 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
423 |
* LOCKS and LOCK Hierarchy ---------------------------------------------------- |
0 | 424 |
* |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
425 |
* There are three locks used in task queues: |
0 | 426 |
* |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
427 |
* 1) The taskq_t's tq_lock, protecting global task queue state. |
0 | 428 |
* |
429 |
* 2) Each per-CPU bucket has a lock for bucket management. |
|
430 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
431 |
* 3) The global taskq_cpupct_lock, which protects the list of |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
432 |
* TASKQ_THREADS_CPU_PCT taskqs. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
433 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
434 |
* If both (1) and (2) are needed, tq_lock should be taken *after* the bucket |
0 | 435 |
* lock. |
436 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
437 |
* If both (1) and (3) are needed, tq_lock should be taken *after* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
438 |
* taskq_cpupct_lock. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
439 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
440 |
* DEBUG FACILITIES ------------------------------------------------------------ |
0 | 441 |
* |
442 |
* For DEBUG kernels it is possible to induce random failures to |
|
443 |
* taskq_dispatch() function when it is given TQ_NOSLEEP argument. The value of |
|
444 |
* taskq_dmtbf and taskq_smtbf tunables control the mean time between induced |
|
445 |
* failures for dynamic and static task queues respectively. |
|
446 |
* |
|
447 |
* Setting TASKQ_STATISTIC to 0 will disable per-bucket statistics. |
|
448 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
449 |
* TUNABLES -------------------------------------------------------------------- |
0 | 450 |
* |
451 |
* system_taskq_size - Size of the global system_taskq. |
|
452 |
* This value is multiplied by nCPUs to determine |
|
453 |
* actual size. |
|
454 |
* Default value: 64 |
|
455 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
456 |
* taskq_minimum_nthreads_max |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
457 |
* - Minimum size of the thread list for a taskq. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
458 |
* Useful for testing different thread pool |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
459 |
* sizes by overwriting tq_nthreads_target. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
460 |
* |
0 | 461 |
* taskq_thread_timeout - Maximum idle time for taskq_d_thread() |
462 |
* Default value: 5 minutes |
|
463 |
* |
|
464 |
* taskq_maxbuckets - Maximum number of buckets in any task queue |
|
465 |
* Default value: 128 |
|
466 |
* |
|
467 |
* taskq_search_depth - Maximum # of buckets searched for a free entry |
|
468 |
* Default value: 4 |
|
469 |
* |
|
470 |
* taskq_dmtbf - Mean time between induced dispatch failures |
|
471 |
* for dynamic task queues. |
|
472 |
* Default value: UINT_MAX (no induced failures) |
|
473 |
* |
|
474 |
* taskq_smtbf - Mean time between induced dispatch failures |
|
475 |
* for static task queues. |
|
476 |
* Default value: UINT_MAX (no induced failures) |
|
477 |
* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
478 |
* CONDITIONAL compilation ----------------------------------------------------- |
0 | 479 |
* |
480 |
* TASKQ_STATISTIC - If set will enable bucket statistic (default). |
|
481 |
* |
|
482 |
*/ |
|
483 |
||
484 |
#include <sys/taskq_impl.h> |
|
485 |
#include <sys/thread.h> |
|
486 |
#include <sys/proc.h> |
|
487 |
#include <sys/kmem.h> |
|
488 |
#include <sys/vmem.h> |
|
489 |
#include <sys/callb.h> |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
490 |
#include <sys/class.h> |
0 | 491 |
#include <sys/systm.h> |
492 |
#include <sys/cmn_err.h> |
|
493 |
#include <sys/debug.h> |
|
494 |
#include <sys/vmsystm.h> /* For throttlefree */ |
|
495 |
#include <sys/sysmacros.h> |
|
496 |
#include <sys/cpuvar.h> |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
497 |
#include <sys/cpupart.h> |
0 | 498 |
#include <sys/sdt.h> |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
499 |
#include <sys/sysdc.h> |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
500 |
#include <sys/note.h> |
0 | 501 |
|
502 |
static kmem_cache_t *taskq_ent_cache, *taskq_cache; |
|
503 |
||
504 |
/* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
505 |
* Pseudo instance numbers for taskqs without explicitly provided instance. |
0 | 506 |
*/ |
507 |
static vmem_t *taskq_id_arena; |
|
508 |
||
509 |
/* Global system task queue for common use */ |
|
510 |
taskq_t *system_taskq; |
|
511 |
||
512 |
/* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
513 |
* Maximum number of entries in global system taskq is |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
514 |
* system_taskq_size * max_ncpus |
0 | 515 |
*/ |
516 |
#define SYSTEM_TASKQ_SIZE 64 |
|
517 |
int system_taskq_size = SYSTEM_TASKQ_SIZE; |
|
518 |
||
519 |
/* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
520 |
* Minimum size for tq_nthreads_max; useful for those who want to play around |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
521 |
* with increasing a taskq's tq_nthreads_target. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
522 |
*/ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
523 |
int taskq_minimum_nthreads_max = 1; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
524 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
525 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
526 |
* We want to ensure that when taskq_create() returns, there is at least |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
527 |
* one thread ready to handle requests. To guarantee this, we have to wait |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
528 |
* for the second thread, since the first one cannot process requests until |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
529 |
* the second thread has been created. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
530 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
531 |
#define TASKQ_CREATE_ACTIVE_THREADS 2 |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
532 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
533 |
/* Maximum percentage allowed for TASKQ_THREADS_CPU_PCT */ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
534 |
#define TASKQ_CPUPCT_MAX_PERCENT 1000 |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
535 |
int taskq_cpupct_max_percent = TASKQ_CPUPCT_MAX_PERCENT; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
536 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
537 |
/* |
0 | 538 |
* Dynamic task queue threads that don't get any work within |
539 |
* taskq_thread_timeout destroy themselves |
|
540 |
*/ |
|
541 |
#define TASKQ_THREAD_TIMEOUT (60 * 5) |
|
542 |
int taskq_thread_timeout = TASKQ_THREAD_TIMEOUT; |
|
543 |
||
544 |
#define TASKQ_MAXBUCKETS 128 |
|
545 |
int taskq_maxbuckets = TASKQ_MAXBUCKETS; |
|
546 |
||
547 |
/* |
|
548 |
* When a bucket has no available entries another buckets are tried. |
|
549 |
* taskq_search_depth parameter limits the amount of buckets that we search |
|
550 |
* before failing. This is mostly useful in systems with many CPUs where we may |
|
551 |
* spend too much time scanning busy buckets. |
|
552 |
*/ |
|
553 |
#define TASKQ_SEARCH_DEPTH 4 |
|
554 |
int taskq_search_depth = TASKQ_SEARCH_DEPTH; |
|
555 |
||
556 |
/* |
|
557 |
* Hashing function: mix various bits of x. May be pretty much anything. |
|
558 |
*/ |
|
559 |
#define TQ_HASH(x) ((x) ^ ((x) >> 11) ^ ((x) >> 17) ^ ((x) ^ 27)) |
|
560 |
||
561 |
/* |
|
562 |
* We do not create any new threads when the system is low on memory and start |
|
563 |
* throttling memory allocations. The following macro tries to estimate such |
|
564 |
* condition. |
|
565 |
*/ |
|
566 |
#define ENOUGH_MEMORY() (freemem > throttlefree) |
|
567 |
||
568 |
/* |
|
569 |
* Static functions. |
|
570 |
*/ |
|
571 |
static taskq_t *taskq_create_common(const char *, int, int, pri_t, int, |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
572 |
int, proc_t *, uint_t, uint_t); |
0 | 573 |
static void taskq_thread(void *); |
574 |
static void taskq_d_thread(taskq_ent_t *); |
|
575 |
static void taskq_bucket_extend(void *); |
|
576 |
static int taskq_constructor(void *, void *, int); |
|
577 |
static void taskq_destructor(void *, void *); |
|
578 |
static int taskq_ent_constructor(void *, void *, int); |
|
579 |
static void taskq_ent_destructor(void *, void *); |
|
580 |
static taskq_ent_t *taskq_ent_alloc(taskq_t *, int); |
|
581 |
static void taskq_ent_free(taskq_t *, taskq_ent_t *); |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
582 |
static int taskq_ent_exists(taskq_t *, task_func_t, void *); |
0 | 583 |
static taskq_ent_t *taskq_bucket_dispatch(taskq_bucket_t *, task_func_t, |
584 |
void *); |
|
585 |
||
586 |
/* |
|
587 |
* Task queues kstats. |
|
588 |
*/ |
|
589 |
struct taskq_kstat { |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
590 |
kstat_named_t tq_pid; |
0 | 591 |
kstat_named_t tq_tasks; |
592 |
kstat_named_t tq_executed; |
|
593 |
kstat_named_t tq_maxtasks; |
|
594 |
kstat_named_t tq_totaltime; |
|
595 |
kstat_named_t tq_nalloc; |
|
596 |
kstat_named_t tq_nactive; |
|
597 |
kstat_named_t tq_pri; |
|
598 |
kstat_named_t tq_nthreads; |
|
599 |
} taskq_kstat = { |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
600 |
{ "pid", KSTAT_DATA_UINT64 }, |
0 | 601 |
{ "tasks", KSTAT_DATA_UINT64 }, |
602 |
{ "executed", KSTAT_DATA_UINT64 }, |
|
603 |
{ "maxtasks", KSTAT_DATA_UINT64 }, |
|
604 |
{ "totaltime", KSTAT_DATA_UINT64 }, |
|
605 |
{ "nactive", KSTAT_DATA_UINT64 }, |
|
606 |
{ "nalloc", KSTAT_DATA_UINT64 }, |
|
607 |
{ "priority", KSTAT_DATA_UINT64 }, |
|
608 |
{ "threads", KSTAT_DATA_UINT64 }, |
|
609 |
}; |
|
610 |
||
611 |
struct taskq_d_kstat { |
|
612 |
kstat_named_t tqd_pri; |
|
613 |
kstat_named_t tqd_btasks; |
|
614 |
kstat_named_t tqd_bexecuted; |
|
615 |
kstat_named_t tqd_bmaxtasks; |
|
616 |
kstat_named_t tqd_bnalloc; |
|
617 |
kstat_named_t tqd_bnactive; |
|
618 |
kstat_named_t tqd_btotaltime; |
|
619 |
kstat_named_t tqd_hits; |
|
620 |
kstat_named_t tqd_misses; |
|
621 |
kstat_named_t tqd_overflows; |
|
622 |
kstat_named_t tqd_tcreates; |
|
623 |
kstat_named_t tqd_tdeaths; |
|
624 |
kstat_named_t tqd_maxthreads; |
|
625 |
kstat_named_t tqd_nomem; |
|
626 |
kstat_named_t tqd_disptcreates; |
|
627 |
kstat_named_t tqd_totaltime; |
|
628 |
kstat_named_t tqd_nalloc; |
|
629 |
kstat_named_t tqd_nfree; |
|
630 |
} taskq_d_kstat = { |
|
631 |
{ "priority", KSTAT_DATA_UINT64 }, |
|
632 |
{ "btasks", KSTAT_DATA_UINT64 }, |
|
633 |
{ "bexecuted", KSTAT_DATA_UINT64 }, |
|
634 |
{ "bmaxtasks", KSTAT_DATA_UINT64 }, |
|
635 |
{ "bnalloc", KSTAT_DATA_UINT64 }, |
|
636 |
{ "bnactive", KSTAT_DATA_UINT64 }, |
|
637 |
{ "btotaltime", KSTAT_DATA_UINT64 }, |
|
638 |
{ "hits", KSTAT_DATA_UINT64 }, |
|
639 |
{ "misses", KSTAT_DATA_UINT64 }, |
|
640 |
{ "overflows", KSTAT_DATA_UINT64 }, |
|
641 |
{ "tcreates", KSTAT_DATA_UINT64 }, |
|
642 |
{ "tdeaths", KSTAT_DATA_UINT64 }, |
|
643 |
{ "maxthreads", KSTAT_DATA_UINT64 }, |
|
644 |
{ "nomem", KSTAT_DATA_UINT64 }, |
|
645 |
{ "disptcreates", KSTAT_DATA_UINT64 }, |
|
646 |
{ "totaltime", KSTAT_DATA_UINT64 }, |
|
647 |
{ "nalloc", KSTAT_DATA_UINT64 }, |
|
648 |
{ "nfree", KSTAT_DATA_UINT64 }, |
|
649 |
}; |
|
650 |
||
651 |
static kmutex_t taskq_kstat_lock; |
|
652 |
static kmutex_t taskq_d_kstat_lock; |
|
653 |
static int taskq_kstat_update(kstat_t *, int); |
|
654 |
static int taskq_d_kstat_update(kstat_t *, int); |
|
655 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
656 |
/* |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
657 |
* List of all TASKQ_THREADS_CPU_PCT taskqs. |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
658 |
*/ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
659 |
static list_t taskq_cpupct_list; /* protected by cpu_lock */ |
0 | 660 |
|
661 |
/* |
|
662 |
* Collect per-bucket statistic when TASKQ_STATISTIC is defined. |
|
663 |
*/ |
|
664 |
#define TASKQ_STATISTIC 1 |
|
665 |
||
666 |
#if TASKQ_STATISTIC |
|
667 |
#define TQ_STAT(b, x) b->tqbucket_stat.x++ |
|
668 |
#else |
|
669 |
#define TQ_STAT(b, x) |
|
670 |
#endif |
|
671 |
||
672 |
/* |
|
673 |
* Random fault injection. |
|
674 |
*/ |
|
675 |
uint_t taskq_random; |
|
676 |
uint_t taskq_dmtbf = UINT_MAX; /* mean time between injected failures */ |
|
677 |
uint_t taskq_smtbf = UINT_MAX; /* mean time between injected failures */ |
|
678 |
||
679 |
/* |
|
680 |
* TQ_NOSLEEP dispatches on dynamic task queues are always allowed to fail. |
|
681 |
* |
|
682 |
* TQ_NOSLEEP dispatches on static task queues can't arbitrarily fail because |
|
683 |
* they could prepopulate the cache and make sure that they do not use more |
|
684 |
* then minalloc entries. So, fault injection in this case insures that |
|
685 |
* either TASKQ_PREPOPULATE is not set or there are more entries allocated |
|
686 |
* than is specified by minalloc. TQ_NOALLOC dispatches are always allowed |
|
687 |
* to fail, but for simplicity we treat them identically to TQ_NOSLEEP |
|
688 |
* dispatches. |
|
689 |
*/ |
|
690 |
#ifdef DEBUG |
|
691 |
#define TASKQ_D_RANDOM_DISPATCH_FAILURE(tq, flag) \ |
|
692 |
taskq_random = (taskq_random * 2416 + 374441) % 1771875;\ |
|
693 |
if ((flag & TQ_NOSLEEP) && \ |
|
694 |
taskq_random < 1771875 / taskq_dmtbf) { \ |
|
695 |
return (NULL); \ |
|
696 |
} |
|
697 |
||
698 |
#define TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flag) \ |
|
699 |
taskq_random = (taskq_random * 2416 + 374441) % 1771875;\ |
|
700 |
if ((flag & (TQ_NOSLEEP | TQ_NOALLOC)) && \ |
|
701 |
(!(tq->tq_flags & TASKQ_PREPOPULATE) || \ |
|
702 |
(tq->tq_nalloc > tq->tq_minalloc)) && \ |
|
703 |
(taskq_random < (1771875 / taskq_smtbf))) { \ |
|
704 |
mutex_exit(&tq->tq_lock); \ |
|
705 |
return (NULL); \ |
|
706 |
} |
|
707 |
#else |
|
708 |
#define TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flag) |
|
709 |
#define TASKQ_D_RANDOM_DISPATCH_FAILURE(tq, flag) |
|
710 |
#endif |
|
711 |
||
712 |
#define IS_EMPTY(l) (((l).tqent_prev == (l).tqent_next) && \ |
|
713 |
((l).tqent_prev == &(l))) |
|
714 |
||
715 |
/* |
|
716 |
* Append `tqe' in the end of the doubly-linked list denoted by l. |
|
717 |
*/ |
|
718 |
#define TQ_APPEND(l, tqe) { \ |
|
719 |
tqe->tqent_next = &l; \ |
|
720 |
tqe->tqent_prev = l.tqent_prev; \ |
|
721 |
tqe->tqent_next->tqent_prev = tqe; \ |
|
722 |
tqe->tqent_prev->tqent_next = tqe; \ |
|
723 |
} |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
724 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
725 |
* Prepend 'tqe' to the beginning of l |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
726 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
727 |
#define TQ_PREPEND(l, tqe) { \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
728 |
tqe->tqent_next = l.tqent_next; \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
729 |
tqe->tqent_prev = &l; \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
730 |
tqe->tqent_next->tqent_prev = tqe; \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
731 |
tqe->tqent_prev->tqent_next = tqe; \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
732 |
} |
0 | 733 |
|
734 |
/* |
|
735 |
* Schedule a task specified by func and arg into the task queue entry tqe. |
|
736 |
*/ |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
737 |
#define TQ_DO_ENQUEUE(tq, tqe, func, arg, front) { \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
738 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
739 |
_NOTE(CONSTCOND) \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
740 |
if (front) { \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
741 |
TQ_PREPEND(tq->tq_task, tqe); \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
742 |
} else { \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
743 |
TQ_APPEND(tq->tq_task, tqe); \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
744 |
} \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
745 |
tqe->tqent_func = (func); \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
746 |
tqe->tqent_arg = (arg); \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
747 |
tq->tq_tasks++; \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
748 |
if (tq->tq_tasks - tq->tq_executed > tq->tq_maxtasks) \ |
0 | 749 |
tq->tq_maxtasks = tq->tq_tasks - tq->tq_executed; \ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
750 |
cv_signal(&tq->tq_dispatch_cv); \ |
0 | 751 |
DTRACE_PROBE2(taskq__enqueue, taskq_t *, tq, taskq_ent_t *, tqe); \ |
752 |
} |
|
753 |
||
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
754 |
#define TQ_ENQUEUE(tq, tqe, func, arg) \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
755 |
TQ_DO_ENQUEUE(tq, tqe, func, arg, 0) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
756 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
757 |
#define TQ_ENQUEUE_FRONT(tq, tqe, func, arg) \ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
758 |
TQ_DO_ENQUEUE(tq, tqe, func, arg, 1) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
759 |
|
0 | 760 |
/* |
761 |
* Do-nothing task which may be used to prepopulate thread caches. |
|
762 |
*/ |
|
763 |
/*ARGSUSED*/ |
|
764 |
void |
|
765 |
nulltask(void *unused) |
|
766 |
{ |
|
767 |
} |
|
768 |
||
769 |
/*ARGSUSED*/ |
|
770 |
static int |
|
771 |
taskq_constructor(void *buf, void *cdrarg, int kmflags) |
|
772 |
{ |
|
773 |
taskq_t *tq = buf; |
|
774 |
||
775 |
bzero(tq, sizeof (taskq_t)); |
|
776 |
||
777 |
mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL); |
|
778 |
rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL); |
|
779 |
cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL); |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
780 |
cv_init(&tq->tq_exit_cv, NULL, CV_DEFAULT, NULL); |
0 | 781 |
cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL); |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
782 |
cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL); |
0 | 783 |
|
784 |
tq->tq_task.tqent_next = &tq->tq_task; |
|
785 |
tq->tq_task.tqent_prev = &tq->tq_task; |
|
786 |
||
787 |
return (0); |
|
788 |
} |
|
789 |
||
790 |
/*ARGSUSED*/ |
|
791 |
static void |
|
792 |
taskq_destructor(void *buf, void *cdrarg) |
|
793 |
{ |
|
794 |
taskq_t *tq = buf; |
|
795 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
796 |
ASSERT(tq->tq_nthreads == 0); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
797 |
ASSERT(tq->tq_buckets == NULL); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
798 |
ASSERT(tq->tq_tcreates == 0); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
799 |
ASSERT(tq->tq_tdeaths == 0); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
800 |
|
0 | 801 |
mutex_destroy(&tq->tq_lock); |
802 |
rw_destroy(&tq->tq_threadlock); |
|
803 |
cv_destroy(&tq->tq_dispatch_cv); |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
804 |
cv_destroy(&tq->tq_exit_cv); |
0 | 805 |
cv_destroy(&tq->tq_wait_cv); |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
806 |
cv_destroy(&tq->tq_maxalloc_cv); |
0 | 807 |
} |
808 |
||
809 |
/*ARGSUSED*/ |
|
810 |
static int |
|
811 |
taskq_ent_constructor(void *buf, void *cdrarg, int kmflags) |
|
812 |
{ |
|
813 |
taskq_ent_t *tqe = buf; |
|
814 |
||
815 |
tqe->tqent_thread = NULL; |
|
816 |
cv_init(&tqe->tqent_cv, NULL, CV_DEFAULT, NULL); |
|
817 |
||
818 |
return (0); |
|
819 |
} |
|
820 |
||
821 |
/*ARGSUSED*/ |
|
822 |
static void |
|
823 |
taskq_ent_destructor(void *buf, void *cdrarg) |
|
824 |
{ |
|
825 |
taskq_ent_t *tqe = buf; |
|
826 |
||
827 |
ASSERT(tqe->tqent_thread == NULL); |
|
828 |
cv_destroy(&tqe->tqent_cv); |
|
829 |
} |
|
830 |
||
831 |
void |
|
832 |
taskq_init(void) |
|
833 |
{ |
|
834 |
taskq_ent_cache = kmem_cache_create("taskq_ent_cache", |
|
835 |
sizeof (taskq_ent_t), 0, taskq_ent_constructor, |
|
836 |
taskq_ent_destructor, NULL, NULL, NULL, 0); |
|
837 |
taskq_cache = kmem_cache_create("taskq_cache", sizeof (taskq_t), |
|
838 |
0, taskq_constructor, taskq_destructor, NULL, NULL, NULL, 0); |
|
839 |
taskq_id_arena = vmem_create("taskq_id_arena", |
|
840 |
(void *)1, INT32_MAX, 1, NULL, NULL, NULL, 0, |
|
841 |
VM_SLEEP | VMC_IDENTIFIER); |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
842 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
843 |
list_create(&taskq_cpupct_list, sizeof (taskq_t), |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
844 |
offsetof(taskq_t, tq_cpupct_link)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
845 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
846 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
847 |
static void |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
848 |
taskq_update_nthreads(taskq_t *tq, uint_t ncpus) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
849 |
{ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
850 |
uint_t newtarget = TASKQ_THREADS_PCT(ncpus, tq->tq_threads_ncpus_pct); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
851 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
852 |
ASSERT(MUTEX_HELD(&cpu_lock)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
853 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
854 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
855 |
/* We must be going from non-zero to non-zero; no exiting. */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
856 |
ASSERT3U(tq->tq_nthreads_target, !=, 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
857 |
ASSERT3U(newtarget, !=, 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
858 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
859 |
ASSERT3U(newtarget, <=, tq->tq_nthreads_max); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
860 |
if (newtarget != tq->tq_nthreads_target) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
861 |
tq->tq_flags |= TASKQ_CHANGING; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
862 |
tq->tq_nthreads_target = newtarget; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
863 |
cv_broadcast(&tq->tq_dispatch_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
864 |
cv_broadcast(&tq->tq_exit_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
865 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
866 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
867 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
868 |
/* called during task queue creation */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
869 |
static void |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
870 |
taskq_cpupct_install(taskq_t *tq, cpupart_t *cpup) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
871 |
{ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
872 |
ASSERT(tq->tq_flags & TASKQ_THREADS_CPU_PCT); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
873 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
874 |
mutex_enter(&cpu_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
875 |
mutex_enter(&tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
876 |
tq->tq_cpupart = cpup->cp_id; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
877 |
taskq_update_nthreads(tq, cpup->cp_ncpus); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
878 |
mutex_exit(&tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
879 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
880 |
list_insert_tail(&taskq_cpupct_list, tq); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
881 |
mutex_exit(&cpu_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
882 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
883 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
884 |
static void |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
885 |
taskq_cpupct_remove(taskq_t *tq) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
886 |
{ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
887 |
ASSERT(tq->tq_flags & TASKQ_THREADS_CPU_PCT); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
888 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
889 |
mutex_enter(&cpu_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
890 |
list_remove(&taskq_cpupct_list, tq); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
891 |
mutex_exit(&cpu_lock); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
892 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
893 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
894 |
/*ARGSUSED*/ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
895 |
static int |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
896 |
taskq_cpu_setup(cpu_setup_t what, int id, void *arg) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
897 |
{ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
898 |
taskq_t *tq; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
899 |
cpupart_t *cp = cpu[id]->cpu_part; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
900 |
uint_t ncpus = cp->cp_ncpus; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
901 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
902 |
ASSERT(MUTEX_HELD(&cpu_lock)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
903 |
ASSERT(ncpus > 0); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
904 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
905 |
switch (what) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
906 |
case CPU_OFF: |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
907 |
case CPU_CPUPART_OUT: |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
908 |
/* offlines are called *before* the cpu is offlined. */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
909 |
if (ncpus > 1) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
910 |
ncpus--; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
911 |
break; |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
912 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
913 |
case CPU_ON: |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
914 |
case CPU_CPUPART_IN: |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
915 |
break; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
916 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
917 |
default: |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
918 |
return (0); /* doesn't affect cpu count */ |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
919 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
920 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
921 |
for (tq = list_head(&taskq_cpupct_list); tq != NULL; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
922 |
tq = list_next(&taskq_cpupct_list, tq)) { |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
923 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
924 |
mutex_enter(&tq->tq_lock); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
925 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
926 |
* If the taskq is part of the cpuset which is changing, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
927 |
* update its nthreads_target. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
928 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
929 |
if (tq->tq_cpupart == cp->cp_id) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
930 |
taskq_update_nthreads(tq, ncpus); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
931 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
932 |
mutex_exit(&tq->tq_lock); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
933 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
934 |
return (0); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
935 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
936 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
937 |
void |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
938 |
taskq_mp_init(void) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
939 |
{ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
940 |
mutex_enter(&cpu_lock); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
941 |
register_cpu_setup_func(taskq_cpu_setup, NULL); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
942 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
943 |
* Make sure we're up to date. At this point in boot, there is only |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
944 |
* one processor set, so we only have to update the current CPU. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
945 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
946 |
(void) taskq_cpu_setup(CPU_ON, CPU->cpu_id, NULL); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
947 |
mutex_exit(&cpu_lock); |
0 | 948 |
} |
949 |
||
950 |
/* |
|
951 |
* Create global system dynamic task queue. |
|
952 |
*/ |
|
953 |
void |
|
954 |
system_taskq_init(void) |
|
955 |
{ |
|
956 |
system_taskq = taskq_create_common("system_taskq", 0, |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
957 |
system_taskq_size * max_ncpus, minclsyspri, 4, 512, &p0, 0, |
0 | 958 |
TASKQ_DYNAMIC | TASKQ_PREPOPULATE); |
959 |
} |
|
960 |
||
961 |
/* |
|
962 |
* taskq_ent_alloc() |
|
963 |
* |
|
964 |
* Allocates a new taskq_ent_t structure either from the free list or from the |
|
965 |
* cache. Returns NULL if it can't be allocated. |
|
966 |
* |
|
967 |
* Assumes: tq->tq_lock is held. |
|
968 |
*/ |
|
969 |
static taskq_ent_t * |
|
970 |
taskq_ent_alloc(taskq_t *tq, int flags) |
|
971 |
{ |
|
972 |
int kmflags = (flags & TQ_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP; |
|
973 |
taskq_ent_t *tqe; |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
974 |
clock_t wait_time; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
975 |
clock_t wait_rv; |
0 | 976 |
|
977 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); |
|
978 |
||
979 |
/* |
|
980 |
* TQ_NOALLOC allocations are allowed to use the freelist, even if |
|
981 |
* we are below tq_minalloc. |
|
982 |
*/ |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
983 |
again: if ((tqe = tq->tq_freelist) != NULL && |
0 | 984 |
((flags & TQ_NOALLOC) || tq->tq_nalloc >= tq->tq_minalloc)) { |
985 |
tq->tq_freelist = tqe->tqent_next; |
|
986 |
} else { |
|
987 |
if (flags & TQ_NOALLOC) |
|
988 |
return (NULL); |
|
989 |
||
990 |
if (tq->tq_nalloc >= tq->tq_maxalloc) { |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
991 |
if (kmflags & KM_NOSLEEP) |
0 | 992 |
return (NULL); |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
993 |
|
0 | 994 |
/* |
995 |
* We don't want to exceed tq_maxalloc, but we can't |
|
996 |
* wait for other tasks to complete (and thus free up |
|
997 |
* task structures) without risking deadlock with |
|
998 |
* the caller. So, we just delay for one second |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
999 |
* to throttle the allocation rate. If we have tasks |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1000 |
* complete before one second timeout expires then |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1001 |
* taskq_ent_free will signal us and we will |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1002 |
* immediately retry the allocation (reap free). |
0 | 1003 |
*/ |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1004 |
wait_time = ddi_get_lbolt() + hz; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1005 |
while (tq->tq_freelist == NULL) { |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1006 |
tq->tq_maxalloc_wait++; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1007 |
wait_rv = cv_timedwait(&tq->tq_maxalloc_cv, |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1008 |
&tq->tq_lock, wait_time); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1009 |
tq->tq_maxalloc_wait--; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1010 |
if (wait_rv == -1) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1011 |
break; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1012 |
} |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1013 |
if (tq->tq_freelist) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1014 |
goto again; /* reap freelist */ |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1015 |
|
0 | 1016 |
} |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1017 |
mutex_exit(&tq->tq_lock); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1018 |
|
0 | 1019 |
tqe = kmem_cache_alloc(taskq_ent_cache, kmflags); |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1020 |
|
0 | 1021 |
mutex_enter(&tq->tq_lock); |
1022 |
if (tqe != NULL) |
|
1023 |
tq->tq_nalloc++; |
|
1024 |
} |
|
1025 |
return (tqe); |
|
1026 |
} |
|
1027 |
||
1028 |
/* |
|
1029 |
* taskq_ent_free() |
|
1030 |
* |
|
1031 |
* Free taskq_ent_t structure by either putting it on the free list or freeing |
|
1032 |
* it to the cache. |
|
1033 |
* |
|
1034 |
* Assumes: tq->tq_lock is held. |
|
1035 |
*/ |
|
1036 |
static void |
|
1037 |
taskq_ent_free(taskq_t *tq, taskq_ent_t *tqe) |
|
1038 |
{ |
|
1039 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); |
|
1040 |
||
1041 |
if (tq->tq_nalloc <= tq->tq_minalloc) { |
|
1042 |
tqe->tqent_next = tq->tq_freelist; |
|
1043 |
tq->tq_freelist = tqe; |
|
1044 |
} else { |
|
1045 |
tq->tq_nalloc--; |
|
1046 |
mutex_exit(&tq->tq_lock); |
|
1047 |
kmem_cache_free(taskq_ent_cache, tqe); |
|
1048 |
mutex_enter(&tq->tq_lock); |
|
1049 |
} |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1050 |
|
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1051 |
if (tq->tq_maxalloc_wait) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1052 |
cv_signal(&tq->tq_maxalloc_cv); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1053 |
} |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1054 |
|
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1055 |
/* |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1056 |
* taskq_ent_exists() |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1057 |
* |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1058 |
* Return 1 if taskq already has entry for calling 'func(arg)'. |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1059 |
* |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1060 |
* Assumes: tq->tq_lock is held. |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1061 |
*/ |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1062 |
static int |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1063 |
taskq_ent_exists(taskq_t *tq, task_func_t func, void *arg) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1064 |
{ |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1065 |
taskq_ent_t *tqe; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1066 |
|
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1067 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1068 |
|
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1069 |
for (tqe = tq->tq_task.tqent_next; tqe != &tq->tq_task; |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1070 |
tqe = tqe->tqent_next) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1071 |
if ((tqe->tqent_func == func) && (tqe->tqent_arg == arg)) |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1072 |
return (1); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1073 |
return (0); |
0 | 1074 |
} |
1075 |
||
1076 |
/* |
|
1077 |
* Dispatch a task "func(arg)" to a free entry of bucket b. |
|
1078 |
* |
|
1079 |
* Assumes: no bucket locks is held. |
|
1080 |
* |
|
1081 |
* Returns: a pointer to an entry if dispatch was successful. |
|
1082 |
* NULL if there are no free entries or if the bucket is suspended. |
|
1083 |
*/ |
|
1084 |
static taskq_ent_t * |
|
1085 |
taskq_bucket_dispatch(taskq_bucket_t *b, task_func_t func, void *arg) |
|
1086 |
{ |
|
1087 |
taskq_ent_t *tqe; |
|
1088 |
||
1089 |
ASSERT(MUTEX_NOT_HELD(&b->tqbucket_lock)); |
|
1090 |
ASSERT(func != NULL); |
|
1091 |
||
1092 |
mutex_enter(&b->tqbucket_lock); |
|
1093 |
||
1094 |
ASSERT(b->tqbucket_nfree != 0 || IS_EMPTY(b->tqbucket_freelist)); |
|
1095 |
ASSERT(b->tqbucket_nfree == 0 || !IS_EMPTY(b->tqbucket_freelist)); |
|
1096 |
||
1097 |
/* |
|
1098 |
* Get en entry from the freelist if there is one. |
|
1099 |
* Schedule task into the entry. |
|
1100 |
*/ |
|
1101 |
if ((b->tqbucket_nfree != 0) && |
|
1102 |
!(b->tqbucket_flags & TQBUCKET_SUSPEND)) { |
|
1103 |
tqe = b->tqbucket_freelist.tqent_prev; |
|
1104 |
||
1105 |
ASSERT(tqe != &b->tqbucket_freelist); |
|
1106 |
ASSERT(tqe->tqent_thread != NULL); |
|
1107 |
||
1108 |
tqe->tqent_prev->tqent_next = tqe->tqent_next; |
|
1109 |
tqe->tqent_next->tqent_prev = tqe->tqent_prev; |
|
1110 |
b->tqbucket_nalloc++; |
|
1111 |
b->tqbucket_nfree--; |
|
1112 |
tqe->tqent_func = func; |
|
1113 |
tqe->tqent_arg = arg; |
|
1114 |
TQ_STAT(b, tqs_hits); |
|
1115 |
cv_signal(&tqe->tqent_cv); |
|
1116 |
DTRACE_PROBE2(taskq__d__enqueue, taskq_bucket_t *, b, |
|
1117 |
taskq_ent_t *, tqe); |
|
1118 |
} else { |
|
1119 |
tqe = NULL; |
|
1120 |
TQ_STAT(b, tqs_misses); |
|
1121 |
} |
|
1122 |
mutex_exit(&b->tqbucket_lock); |
|
1123 |
return (tqe); |
|
1124 |
} |
|
1125 |
||
1126 |
/* |
|
1127 |
* Dispatch a task. |
|
1128 |
* |
|
1129 |
* Assumes: func != NULL |
|
1130 |
* |
|
1131 |
* Returns: NULL if dispatch failed. |
|
1132 |
* non-NULL if task dispatched successfully. |
|
1133 |
* Actual return value is the pointer to taskq entry that was used to |
|
1134 |
* dispatch a task. This is useful for debugging. |
|
1135 |
*/ |
|
1136 |
taskqid_t |
|
1137 |
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) |
|
1138 |
{ |
|
1139 |
taskq_bucket_t *bucket = NULL; /* Which bucket needs extension */ |
|
1140 |
taskq_ent_t *tqe = NULL; |
|
1141 |
taskq_ent_t *tqe1; |
|
1142 |
uint_t bsize; |
|
1143 |
||
1144 |
ASSERT(tq != NULL); |
|
1145 |
ASSERT(func != NULL); |
|
1146 |
||
1147 |
if (!(tq->tq_flags & TASKQ_DYNAMIC)) { |
|
1148 |
/* |
|
1149 |
* TQ_NOQUEUE flag can't be used with non-dynamic task queues. |
|
1150 |
*/ |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1151 |
ASSERT(!(flags & TQ_NOQUEUE)); |
0 | 1152 |
/* |
1153 |
* Enqueue the task to the underlying queue. |
|
1154 |
*/ |
|
1155 |
mutex_enter(&tq->tq_lock); |
|
1156 |
||
1157 |
TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flags); |
|
1158 |
||
1159 |
if ((tqe = taskq_ent_alloc(tq, flags)) == NULL) { |
|
1160 |
mutex_exit(&tq->tq_lock); |
|
1161 |
return (NULL); |
|
1162 |
} |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1163 |
/* Make sure we start without any flags */ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1164 |
tqe->tqent_un.tqent_flags = 0; |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1165 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1166 |
if (flags & TQ_FRONT) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1167 |
TQ_ENQUEUE_FRONT(tq, tqe, func, arg); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1168 |
} else { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1169 |
TQ_ENQUEUE(tq, tqe, func, arg); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1170 |
} |
0 | 1171 |
mutex_exit(&tq->tq_lock); |
1172 |
return ((taskqid_t)tqe); |
|
1173 |
} |
|
1174 |
||
1175 |
/* |
|
1176 |
* Dynamic taskq dispatching. |
|
1177 |
*/ |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1178 |
ASSERT(!(flags & (TQ_NOALLOC | TQ_FRONT))); |
0 | 1179 |
TASKQ_D_RANDOM_DISPATCH_FAILURE(tq, flags); |
1180 |
||
1181 |
bsize = tq->tq_nbuckets; |
|
1182 |
||
1183 |
if (bsize == 1) { |
|
1184 |
/* |
|
1185 |
* In a single-CPU case there is only one bucket, so get |
|
1186 |
* entry directly from there. |
|
1187 |
*/ |
|
1188 |
if ((tqe = taskq_bucket_dispatch(tq->tq_buckets, func, arg)) |
|
1189 |
!= NULL) |
|
1190 |
return ((taskqid_t)tqe); /* Fastpath */ |
|
1191 |
bucket = tq->tq_buckets; |
|
1192 |
} else { |
|
1193 |
int loopcount; |
|
1194 |
taskq_bucket_t *b; |
|
1195 |
uintptr_t h = ((uintptr_t)CPU + (uintptr_t)arg) >> 3; |
|
1196 |
||
1197 |
h = TQ_HASH(h); |
|
1198 |
||
1199 |
/* |
|
1200 |
* The 'bucket' points to the original bucket that we hit. If we |
|
1201 |
* can't allocate from it, we search other buckets, but only |
|
1202 |
* extend this one. |
|
1203 |
*/ |
|
1204 |
b = &tq->tq_buckets[h & (bsize - 1)]; |
|
1205 |
ASSERT(b->tqbucket_taskq == tq); /* Sanity check */ |
|
1206 |
||
1207 |
/* |
|
1208 |
* Do a quick check before grabbing the lock. If the bucket does |
|
1209 |
* not have free entries now, chances are very small that it |
|
1210 |
* will after we take the lock, so we just skip it. |
|
1211 |
*/ |
|
1212 |
if (b->tqbucket_nfree != 0) { |
|
1213 |
if ((tqe = taskq_bucket_dispatch(b, func, arg)) != NULL) |
|
1214 |
return ((taskqid_t)tqe); /* Fastpath */ |
|
1215 |
} else { |
|
1216 |
TQ_STAT(b, tqs_misses); |
|
1217 |
} |
|
1218 |
||
1219 |
bucket = b; |
|
1220 |
loopcount = MIN(taskq_search_depth, bsize); |
|
1221 |
/* |
|
1222 |
* If bucket dispatch failed, search loopcount number of buckets |
|
1223 |
* before we give up and fail. |
|
1224 |
*/ |
|
1225 |
do { |
|
1226 |
b = &tq->tq_buckets[++h & (bsize - 1)]; |
|
1227 |
ASSERT(b->tqbucket_taskq == tq); /* Sanity check */ |
|
1228 |
loopcount--; |
|
1229 |
||
1230 |
if (b->tqbucket_nfree != 0) { |
|
1231 |
tqe = taskq_bucket_dispatch(b, func, arg); |
|
1232 |
} else { |
|
1233 |
TQ_STAT(b, tqs_misses); |
|
1234 |
} |
|
1235 |
} while ((tqe == NULL) && (loopcount > 0)); |
|
1236 |
} |
|
1237 |
||
1238 |
/* |
|
1239 |
* At this point we either scheduled a task and (tqe != NULL) or failed |
|
1240 |
* (tqe == NULL). Try to recover from fails. |
|
1241 |
*/ |
|
1242 |
||
1243 |
/* |
|
1244 |
* For KM_SLEEP dispatches, try to extend the bucket and retry dispatch. |
|
1245 |
*/ |
|
1246 |
if ((tqe == NULL) && !(flags & TQ_NOSLEEP)) { |
|
1247 |
/* |
|
1248 |
* taskq_bucket_extend() may fail to do anything, but this is |
|
1249 |
* fine - we deal with it later. If the bucket was successfully |
|
1250 |
* extended, there is a good chance that taskq_bucket_dispatch() |
|
1251 |
* will get this new entry, unless someone is racing with us and |
|
1252 |
* stealing the new entry from under our nose. |
|
1253 |
* taskq_bucket_extend() may sleep. |
|
1254 |
*/ |
|
1255 |
taskq_bucket_extend(bucket); |
|
1256 |
TQ_STAT(bucket, tqs_disptcreates); |
|
1257 |
if ((tqe = taskq_bucket_dispatch(bucket, func, arg)) != NULL) |
|
1258 |
return ((taskqid_t)tqe); |
|
1259 |
} |
|
1260 |
||
1261 |
ASSERT(bucket != NULL); |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1262 |
|
0 | 1263 |
/* |
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1264 |
* Since there are not enough free entries in the bucket, add a |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1265 |
* taskq entry to extend it in the background using backing queue |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1266 |
* (unless we already have a taskq entry to perform that extension). |
0 | 1267 |
*/ |
1268 |
mutex_enter(&tq->tq_lock); |
|
11854
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1269 |
if (!taskq_ent_exists(tq, taskq_bucket_extend, bucket)) { |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1270 |
if ((tqe1 = taskq_ent_alloc(tq, TQ_NOSLEEP)) != NULL) { |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1271 |
TQ_ENQUEUE_FRONT(tq, tqe1, taskq_bucket_extend, bucket); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1272 |
} else { |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1273 |
TQ_STAT(bucket, tqs_nomem); |
5351ddd19d45
6900839 taskq_ent_alloc: TQ_SLEEP performance cliff when tq_nalloc > tq_maxalloc
Chris Horne <Chris.Horne@Sun.COM>
parents:
11474
diff
changeset
|
1274 |
} |
0 | 1275 |
} |
1276 |
||
1277 |
/* |
|
1278 |
* Dispatch failed and we can't find an entry to schedule a task. |
|
1279 |
* Revert to the backing queue unless TQ_NOQUEUE was asked. |
|
1280 |
*/ |
|
1281 |
if ((tqe == NULL) && !(flags & TQ_NOQUEUE)) { |
|
1282 |
if ((tqe = taskq_ent_alloc(tq, flags)) != NULL) { |
|
1283 |
TQ_ENQUEUE(tq, tqe, func, arg); |
|
1284 |
} else { |
|
1285 |
TQ_STAT(bucket, tqs_nomem); |
|
1286 |
} |
|
1287 |
} |
|
1288 |
mutex_exit(&tq->tq_lock); |
|
1289 |
||
1290 |
return ((taskqid_t)tqe); |
|
1291 |
} |
|
1292 |
||
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1293 |
void |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1294 |
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags, |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1295 |
taskq_ent_t *tqe) |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1296 |
{ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1297 |
ASSERT(func != NULL); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1298 |
ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC)); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1299 |
|
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1300 |
/* |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1301 |
* Mark it as a prealloc'd task. This is important |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1302 |
* to ensure that we don't free it later. |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1303 |
*/ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1304 |
tqe->tqent_un.tqent_flags |= TQENT_FLAG_PREALLOC; |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1305 |
/* |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1306 |
* Enqueue the task to the underlying queue. |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1307 |
*/ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1308 |
mutex_enter(&tq->tq_lock); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1309 |
|
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1310 |
if (flags & TQ_FRONT) { |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1311 |
TQ_ENQUEUE_FRONT(tq, tqe, func, arg); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1312 |
} else { |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1313 |
TQ_ENQUEUE(tq, tqe, func, arg); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1314 |
} |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1315 |
mutex_exit(&tq->tq_lock); |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1316 |
} |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1317 |
|
0 | 1318 |
/* |
1319 |
* Wait for all pending tasks to complete. |
|
1320 |
* Calling taskq_wait from a task will cause deadlock. |
|
1321 |
*/ |
|
1322 |
void |
|
1323 |
taskq_wait(taskq_t *tq) |
|
1324 |
{ |
|
1325 |
ASSERT(tq != curthread->t_taskq); |
|
1326 |
||
1327 |
mutex_enter(&tq->tq_lock); |
|
1328 |
while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0) |
|
1329 |
cv_wait(&tq->tq_wait_cv, &tq->tq_lock); |
|
1330 |
mutex_exit(&tq->tq_lock); |
|
1331 |
||
1332 |
if (tq->tq_flags & TASKQ_DYNAMIC) { |
|
1333 |
taskq_bucket_t *b = tq->tq_buckets; |
|
1334 |
int bid = 0; |
|
1335 |
for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) { |
|
1336 |
mutex_enter(&b->tqbucket_lock); |
|
1337 |
while (b->tqbucket_nalloc > 0) |
|
1338 |
cv_wait(&b->tqbucket_cv, &b->tqbucket_lock); |
|
1339 |
mutex_exit(&b->tqbucket_lock); |
|
1340 |
} |
|
1341 |
} |
|
1342 |
} |
|
1343 |
||
1344 |
/* |
|
1345 |
* Suspend execution of tasks. |
|
1346 |
* |
|
1347 |
* Tasks in the queue part will be suspended immediately upon return from this |
|
1348 |
* function. Pending tasks in the dynamic part will continue to execute, but all |
|
1349 |
* new tasks will be suspended. |
|
1350 |
*/ |
|
1351 |
void |
|
1352 |
taskq_suspend(taskq_t *tq) |
|
1353 |
{ |
|
1354 |
rw_enter(&tq->tq_threadlock, RW_WRITER); |
|
1355 |
||
1356 |
if (tq->tq_flags & TASKQ_DYNAMIC) { |
|
1357 |
taskq_bucket_t *b = tq->tq_buckets; |
|
1358 |
int bid = 0; |
|
1359 |
for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) { |
|
1360 |
mutex_enter(&b->tqbucket_lock); |
|
1361 |
b->tqbucket_flags |= TQBUCKET_SUSPEND; |
|
1362 |
mutex_exit(&b->tqbucket_lock); |
|
1363 |
} |
|
1364 |
} |
|
1365 |
/* |
|
1366 |
* Mark task queue as being suspended. Needed for taskq_suspended(). |
|
1367 |
*/ |
|
1368 |
mutex_enter(&tq->tq_lock); |
|
1369 |
ASSERT(!(tq->tq_flags & TASKQ_SUSPENDED)); |
|
1370 |
tq->tq_flags |= TASKQ_SUSPENDED; |
|
1371 |
mutex_exit(&tq->tq_lock); |
|
1372 |
} |
|
1373 |
||
1374 |
/* |
|
1375 |
* returns: 1 if tq is suspended, 0 otherwise. |
|
1376 |
*/ |
|
1377 |
int |
|
1378 |
taskq_suspended(taskq_t *tq) |
|
1379 |
{ |
|
1380 |
return ((tq->tq_flags & TASKQ_SUSPENDED) != 0); |
|
1381 |
} |
|
1382 |
||
1383 |
/* |
|
1384 |
* Resume taskq execution. |
|
1385 |
*/ |
|
1386 |
void |
|
1387 |
taskq_resume(taskq_t *tq) |
|
1388 |
{ |
|
1389 |
ASSERT(RW_WRITE_HELD(&tq->tq_threadlock)); |
|
1390 |
||
1391 |
if (tq->tq_flags & TASKQ_DYNAMIC) { |
|
1392 |
taskq_bucket_t *b = tq->tq_buckets; |
|
1393 |
int bid = 0; |
|
1394 |
for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) { |
|
1395 |
mutex_enter(&b->tqbucket_lock); |
|
1396 |
b->tqbucket_flags &= ~TQBUCKET_SUSPEND; |
|
1397 |
mutex_exit(&b->tqbucket_lock); |
|
1398 |
} |
|
1399 |
} |
|
1400 |
mutex_enter(&tq->tq_lock); |
|
1401 |
ASSERT(tq->tq_flags & TASKQ_SUSPENDED); |
|
1402 |
tq->tq_flags &= ~TASKQ_SUSPENDED; |
|
1403 |
mutex_exit(&tq->tq_lock); |
|
1404 |
||
1405 |
rw_exit(&tq->tq_threadlock); |
|
1406 |
} |
|
1407 |
||
1408 |
int |
|
1409 |
taskq_member(taskq_t *tq, kthread_t *thread) |
|
1410 |
{ |
|
1411 |
return (thread->t_taskq == tq); |
|
1412 |
} |
|
1413 |
||
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1414 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1415 |
* Creates a thread in the taskq. We only allow one outstanding create at |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1416 |
* a time. We drop and reacquire the tq_lock in order to avoid blocking other |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1417 |
* taskq activity while thread_create() or lwp_kernel_create() run. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1418 |
* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1419 |
* The first time we're called, we do some additional setup, and do not |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1420 |
* return until there are enough threads to start servicing requests. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1421 |
*/ |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1422 |
static void |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1423 |
taskq_thread_create(taskq_t *tq) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1424 |
{ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1425 |
kthread_t *t; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1426 |
const boolean_t first = (tq->tq_nthreads == 0); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1427 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1428 |
ASSERT(MUTEX_HELD(&tq->tq_lock)); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1429 |
ASSERT(tq->tq_flags & TASKQ_CHANGING); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1430 |
ASSERT(tq->tq_nthreads < tq->tq_nthreads_target); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1431 |
ASSERT(!(tq->tq_flags & TASKQ_THREAD_CREATED)); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1432 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1433 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1434 |
tq->tq_flags |= TASKQ_THREAD_CREATED; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1435 |
tq->tq_active++; |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1436 |
mutex_exit(&tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1437 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1438 |
if (tq->tq_proc != &p0) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1439 |
t = lwp_kernel_create(tq->tq_proc, taskq_thread, tq, TS_RUN, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1440 |
tq->tq_pri); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1441 |
} else { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1442 |
t = thread_create(NULL, 0, taskq_thread, tq, 0, &p0, TS_RUN, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1443 |
tq->tq_pri); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1444 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1445 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1446 |
if (!first) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1447 |
mutex_enter(&tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1448 |
return; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1449 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1450 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1451 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1452 |
* We know the thread cannot go away, since tq cannot be |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1453 |
* destroyed until creation has completed. We can therefore |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1454 |
* safely dereference t. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1455 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1456 |
if (tq->tq_flags & TASKQ_THREADS_CPU_PCT) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1457 |
taskq_cpupct_install(tq, t->t_cpupart); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1458 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1459 |
mutex_enter(&tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1460 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1461 |
/* Wait until we can service requests. */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1462 |
while (tq->tq_nthreads != tq->tq_nthreads_target && |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1463 |
tq->tq_nthreads < TASKQ_CREATE_ACTIVE_THREADS) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1464 |
cv_wait(&tq->tq_wait_cv, &tq->tq_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1465 |
} |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1466 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1467 |
|
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1468 |
/* |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1469 |
* Common "sleep taskq thread" function, which handles CPR stuff, as well |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1470 |
* as giving a nice common point for debuggers to find inactive threads. |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1471 |
*/ |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1472 |
static clock_t |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1473 |
taskq_thread_wait(taskq_t *tq, kmutex_t *mx, kcondvar_t *cv, |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1474 |
callb_cpr_t *cprinfo, clock_t timeout) |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1475 |
{ |
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1476 |
clock_t ret = 0; |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1477 |
|
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1478 |
if (!(tq->tq_flags & TASKQ_CPR_SAFE)) { |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1479 |
CALLB_CPR_SAFE_BEGIN(cprinfo); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1480 |
} |
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1481 |
if (timeout < 0) |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1482 |
cv_wait(cv, mx); |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1483 |
else |
11066
cebb50cbe4f9
PSARC/2009/396 Tickless Kernel Architecture / lbolt decoupling
Rafael Vanoni <rafael.vanoni@sun.com>
parents:
10889
diff
changeset
|
1484 |
ret = cv_reltimedwait(cv, mx, timeout, TR_CLOCK_TICK); |
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1485 |
|
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1486 |
if (!(tq->tq_flags & TASKQ_CPR_SAFE)) { |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1487 |
CALLB_CPR_SAFE_END(cprinfo, mx); |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1488 |
} |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1489 |
|
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1490 |
return (ret); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1491 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1492 |
|
0 | 1493 |
/* |
1494 |
* Worker thread for processing task queue. |
|
1495 |
*/ |
|
1496 |
static void |
|
1497 |
taskq_thread(void *arg) |
|
1498 |
{ |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1499 |
int thread_id; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1500 |
|
0 | 1501 |
taskq_t *tq = arg; |
1502 |
taskq_ent_t *tqe; |
|
1503 |
callb_cpr_t cprinfo; |
|
1504 |
hrtime_t start, end; |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1505 |
boolean_t freeit; |
0 | 1506 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1507 |
curthread->t_taskq = tq; /* mark ourselves for taskq_member() */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1508 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1509 |
if (curproc != &p0 && (tq->tq_flags & TASKQ_DUTY_CYCLE)) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1510 |
sysdc_thread_enter(curthread, tq->tq_DC, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1511 |
(tq->tq_flags & TASKQ_DC_BATCH) ? SYSDC_THREAD_BATCH : 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1512 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1513 |
|
0 | 1514 |
if (tq->tq_flags & TASKQ_CPR_SAFE) { |
1515 |
CALLB_CPR_INIT_SAFE(curthread, tq->tq_name); |
|
1516 |
} else { |
|
1517 |
CALLB_CPR_INIT(&cprinfo, &tq->tq_lock, callb_generic_cpr, |
|
1518 |
tq->tq_name); |
|
1519 |
} |
|
1520 |
mutex_enter(&tq->tq_lock); |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1521 |
thread_id = ++tq->tq_nthreads; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1522 |
ASSERT(tq->tq_flags & TASKQ_THREAD_CREATED); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1523 |
ASSERT(tq->tq_flags & TASKQ_CHANGING); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1524 |
tq->tq_flags &= ~TASKQ_THREAD_CREATED; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1525 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1526 |
VERIFY3S(thread_id, <=, tq->tq_nthreads_max); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1527 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1528 |
if (tq->tq_nthreads_max == 1) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1529 |
tq->tq_thread = curthread; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1530 |
else |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1531 |
tq->tq_threadlist[thread_id - 1] = curthread; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1532 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1533 |
/* Allow taskq_create_common()'s taskq_thread_create() to return. */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1534 |
if (tq->tq_nthreads == TASKQ_CREATE_ACTIVE_THREADS) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1535 |
cv_broadcast(&tq->tq_wait_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1536 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1537 |
for (;;) { |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1538 |
if (tq->tq_flags & TASKQ_CHANGING) { |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1539 |
/* See if we're no longer needed */ |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1540 |
if (thread_id > tq->tq_nthreads_target) { |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1541 |
/* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1542 |
* To preserve the one-to-one mapping between |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1543 |
* thread_id and thread, we must exit from |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1544 |
* highest thread ID to least. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1545 |
* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1546 |
* However, if everyone is exiting, the order |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1547 |
* doesn't matter, so just exit immediately. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1548 |
* (this is safe, since you must wait for |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1549 |
* nthreads to reach 0 after setting |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1550 |
* tq_nthreads_target to 0) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1551 |
*/ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1552 |
if (thread_id == tq->tq_nthreads || |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1553 |
tq->tq_nthreads_target == 0) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1554 |
break; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1555 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1556 |
/* Wait for higher thread_ids to exit */ |
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1557 |
(void) taskq_thread_wait(tq, &tq->tq_lock, |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1558 |
&tq->tq_exit_cv, &cprinfo, -1); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1559 |
continue; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1560 |
} |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1561 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1562 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1563 |
* If no thread is starting taskq_thread(), we can |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1564 |
* do some bookkeeping. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1565 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1566 |
if (!(tq->tq_flags & TASKQ_THREAD_CREATED)) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1567 |
/* Check if we've reached our target */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1568 |
if (tq->tq_nthreads == tq->tq_nthreads_target) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1569 |
tq->tq_flags &= ~TASKQ_CHANGING; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1570 |
cv_broadcast(&tq->tq_wait_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1571 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1572 |
/* Check if we need to create a thread */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1573 |
if (tq->tq_nthreads < tq->tq_nthreads_target) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1574 |
taskq_thread_create(tq); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1575 |
continue; /* tq_lock was dropped */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1576 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1577 |
} |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1578 |
} |
0 | 1579 |
if ((tqe = tq->tq_task.tqent_next) == &tq->tq_task) { |
1580 |
if (--tq->tq_active == 0) |
|
1581 |
cv_broadcast(&tq->tq_wait_cv); |
|
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1582 |
(void) taskq_thread_wait(tq, &tq->tq_lock, |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1583 |
&tq->tq_dispatch_cv, &cprinfo, -1); |
0 | 1584 |
tq->tq_active++; |
1585 |
continue; |
|
1586 |
} |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1587 |
|
0 | 1588 |
tqe->tqent_prev->tqent_next = tqe->tqent_next; |
1589 |
tqe->tqent_next->tqent_prev = tqe->tqent_prev; |
|
1590 |
mutex_exit(&tq->tq_lock); |
|
1591 |
||
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1592 |
/* |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1593 |
* For prealloc'd tasks, we don't free anything. We |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1594 |
* have to check this now, because once we call the |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1595 |
* function for a prealloc'd taskq, we can't touch the |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1596 |
* tqent any longer (calling the function returns the |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1597 |
* ownershp of the tqent back to caller of |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1598 |
* taskq_dispatch.) |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1599 |
*/ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1600 |
if ((!(tq->tq_flags & TASKQ_DYNAMIC)) && |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1601 |
(tqe->tqent_un.tqent_flags & TQENT_FLAG_PREALLOC)) { |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1602 |
/* clear pointers to assist assertion checks */ |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1603 |
tqe->tqent_next = tqe->tqent_prev = NULL; |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1604 |
freeit = B_FALSE; |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1605 |
} else { |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1606 |
freeit = B_TRUE; |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1607 |
} |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1608 |
|
0 | 1609 |
rw_enter(&tq->tq_threadlock, RW_READER); |
1610 |
start = gethrtime(); |
|
1611 |
DTRACE_PROBE2(taskq__exec__start, taskq_t *, tq, |
|
1612 |
taskq_ent_t *, tqe); |
|
1613 |
tqe->tqent_func(tqe->tqent_arg); |
|
1614 |
DTRACE_PROBE2(taskq__exec__end, taskq_t *, tq, |
|
1615 |
taskq_ent_t *, tqe); |
|
1616 |
end = gethrtime(); |
|
1617 |
rw_exit(&tq->tq_threadlock); |
|
1618 |
||
1619 |
mutex_enter(&tq->tq_lock); |
|
1620 |
tq->tq_totaltime += end - start; |
|
1621 |
tq->tq_executed++; |
|
1622 |
||
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1623 |
if (freeit) |
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1624 |
taskq_ent_free(tq, tqe); |
0 | 1625 |
} |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1626 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1627 |
if (tq->tq_nthreads_max == 1) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1628 |
tq->tq_thread = NULL; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1629 |
else |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1630 |
tq->tq_threadlist[thread_id - 1] = NULL; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1631 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1632 |
/* We're exiting, and therefore no longer active */ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1633 |
ASSERT(tq->tq_active > 0); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1634 |
tq->tq_active--; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1635 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1636 |
ASSERT(tq->tq_nthreads > 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1637 |
tq->tq_nthreads--; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1638 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1639 |
/* Wake up anyone waiting for us to exit */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1640 |
cv_broadcast(&tq->tq_exit_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1641 |
if (tq->tq_nthreads == tq->tq_nthreads_target) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1642 |
if (!(tq->tq_flags & TASKQ_THREAD_CREATED)) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1643 |
tq->tq_flags &= ~TASKQ_CHANGING; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1644 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1645 |
cv_broadcast(&tq->tq_wait_cv); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1646 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1647 |
|
0 | 1648 |
ASSERT(!(tq->tq_flags & TASKQ_CPR_SAFE)); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1649 |
CALLB_CPR_EXIT(&cprinfo); /* drops tq->tq_lock */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1650 |
if (curthread->t_lwp != NULL) { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1651 |
mutex_enter(&curproc->p_lock); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1652 |
lwp_exit(); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1653 |
} else { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1654 |
thread_exit(); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1655 |
} |
0 | 1656 |
} |
1657 |
||
1658 |
/* |
|
1659 |
* Worker per-entry thread for dynamic dispatches. |
|
1660 |
*/ |
|
1661 |
static void |
|
1662 |
taskq_d_thread(taskq_ent_t *tqe) |
|
1663 |
{ |
|
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
1664 |
taskq_bucket_t *bucket = tqe->tqent_un.tqent_bucket; |
0 | 1665 |
taskq_t *tq = bucket->tqbucket_taskq; |
1666 |
kmutex_t *lock = &bucket->tqbucket_lock; |
|
1667 |
kcondvar_t *cv = &tqe->tqent_cv; |
|
1668 |
callb_cpr_t cprinfo; |
|
1669 |
clock_t w; |
|
1670 |
||
1671 |
CALLB_CPR_INIT(&cprinfo, lock, callb_generic_cpr, tq->tq_name); |
|
1672 |
||
1673 |
mutex_enter(lock); |
|
1674 |
||
1675 |
for (;;) { |
|
1676 |
/* |
|
1677 |
* If a task is scheduled (func != NULL), execute it, otherwise |
|
1678 |
* sleep, waiting for a job. |
|
1679 |
*/ |
|
1680 |
if (tqe->tqent_func != NULL) { |
|
1681 |
hrtime_t start; |
|
1682 |
hrtime_t end; |
|
1683 |
||
1684 |
ASSERT(bucket->tqbucket_nalloc > 0); |
|
1685 |
||
1686 |
/* |
|
1687 |
* It is possible to free the entry right away before |
|
1688 |
* actually executing the task so that subsequent |
|
1689 |
* dispatches may immediately reuse it. But this, |
|
1690 |
* effectively, creates a two-length queue in the entry |
|
1691 |
* and may lead to a deadlock if the execution of the |
|
1692 |
* current task depends on the execution of the next |
|
1693 |
* scheduled task. So, we keep the entry busy until the |
|
1694 |
* task is processed. |
|
1695 |
*/ |
|
1696 |
||
1697 |
mutex_exit(lock); |
|
1698 |
start = gethrtime(); |
|
1699 |
DTRACE_PROBE3(taskq__d__exec__start, taskq_t *, tq, |
|
1700 |
taskq_bucket_t *, bucket, taskq_ent_t *, tqe); |
|
1701 |
tqe->tqent_func(tqe->tqent_arg); |
|
1702 |
DTRACE_PROBE3(taskq__d__exec__end, taskq_t *, tq, |
|
1703 |
taskq_bucket_t *, bucket, taskq_ent_t *, tqe); |
|
1704 |
end = gethrtime(); |
|
1705 |
mutex_enter(lock); |
|
1706 |
bucket->tqbucket_totaltime += end - start; |
|
1707 |
||
1708 |
/* |
|
1709 |
* Return the entry to the bucket free list. |
|
1710 |
*/ |
|
1711 |
tqe->tqent_func = NULL; |
|
1712 |
TQ_APPEND(bucket->tqbucket_freelist, tqe); |
|
1713 |
bucket->tqbucket_nalloc--; |
|
1714 |
bucket->tqbucket_nfree++; |
|
1715 |
ASSERT(!IS_EMPTY(bucket->tqbucket_freelist)); |
|
1716 |
/* |
|
1717 |
* taskq_wait() waits for nalloc to drop to zero on |
|
1718 |
* tqbucket_cv. |
|
1719 |
*/ |
|
1720 |
cv_signal(&bucket->tqbucket_cv); |
|
1721 |
} |
|
1722 |
||
1723 |
/* |
|
1724 |
* At this point the entry must be in the bucket free list - |
|
1725 |
* either because it was there initially or because it just |
|
1726 |
* finished executing a task and put itself on the free list. |
|
1727 |
*/ |
|
1728 |
ASSERT(bucket->tqbucket_nfree > 0); |
|
1729 |
/* |
|
1730 |
* Go to sleep unless we are closing. |
|
1731 |
* If a thread is sleeping too long, it dies. |
|
1732 |
*/ |
|
1733 |
if (! (bucket->tqbucket_flags & TQBUCKET_CLOSE)) { |
|
10889
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1734 |
w = taskq_thread_wait(tq, lock, cv, |
8b6ec68049bd
6888456 zfs command line utilities should have CTF data
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
9515
diff
changeset
|
1735 |
&cprinfo, taskq_thread_timeout * hz); |
0 | 1736 |
} |
1737 |
||
1738 |
/* |
|
1739 |
* At this point we may be in two different states: |
|
1740 |
* |
|
1741 |
* (1) tqent_func is set which means that a new task is |
|
1742 |
* dispatched and we need to execute it. |
|
1743 |
* |
|
1744 |
* (2) Thread is sleeping for too long or we are closing. In |
|
1745 |
* both cases destroy the thread and the entry. |
|
1746 |
*/ |
|
1747 |
||
1748 |
/* If func is NULL we should be on the freelist. */ |
|
1749 |
ASSERT((tqe->tqent_func != NULL) || |
|
1750 |
(bucket->tqbucket_nfree > 0)); |
|
1751 |
/* If func is non-NULL we should be allocated */ |
|
1752 |
ASSERT((tqe->tqent_func == NULL) || |
|
1753 |
(bucket->tqbucket_nalloc > 0)); |
|
1754 |
||
1755 |
/* Check freelist consistency */ |
|
1756 |
ASSERT((bucket->tqbucket_nfree > 0) || |
|
1757 |
IS_EMPTY(bucket->tqbucket_freelist)); |
|
1758 |
ASSERT((bucket->tqbucket_nfree == 0) || |
|
1759 |
!IS_EMPTY(bucket->tqbucket_freelist)); |
|
1760 |
||
1761 |
if ((tqe->tqent_func == NULL) && |
|
1762 |
((w == -1) || (bucket->tqbucket_flags & TQBUCKET_CLOSE))) { |
|
1763 |
/* |
|
1764 |
* This thread is sleeping for too long or we are |
|
1765 |
* closing - time to die. |
|
1766 |
* Thread creation/destruction happens rarely, |
|
1767 |
* so grabbing the lock is not a big performance issue. |
|
1768 |
* The bucket lock is dropped by CALLB_CPR_EXIT(). |
|
1769 |
*/ |
|
1770 |
||
1771 |
/* Remove the entry from the free list. */ |
|
1772 |
tqe->tqent_prev->tqent_next = tqe->tqent_next; |
|
1773 |
tqe->tqent_next->tqent_prev = tqe->tqent_prev; |
|
1774 |
ASSERT(bucket->tqbucket_nfree > 0); |
|
1775 |
bucket->tqbucket_nfree--; |
|
1776 |
||
1777 |
TQ_STAT(bucket, tqs_tdeaths); |
|
1778 |
cv_signal(&bucket->tqbucket_cv); |
|
1779 |
tqe->tqent_thread = NULL; |
|
1780 |
mutex_enter(&tq->tq_lock); |
|
1781 |
tq->tq_tdeaths++; |
|
1782 |
mutex_exit(&tq->tq_lock); |
|
1783 |
CALLB_CPR_EXIT(&cprinfo); |
|
1784 |
kmem_cache_free(taskq_ent_cache, tqe); |
|
1785 |
thread_exit(); |
|
1786 |
} |
|
1787 |
} |
|
1788 |
} |
|
1789 |
||
1790 |
||
1791 |
/* |
|
1792 |
* Taskq creation. May sleep for memory. |
|
1793 |
* Always use automatically generated instances to avoid kstat name space |
|
1794 |
* collisions. |
|
1795 |
*/ |
|
1796 |
||
1797 |
taskq_t * |
|
1798 |
taskq_create(const char *name, int nthreads, pri_t pri, int minalloc, |
|
1799 |
int maxalloc, uint_t flags) |
|
1800 |
{ |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1801 |
ASSERT((flags & ~TASKQ_INTERFACE_FLAGS) == 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1802 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1803 |
return (taskq_create_common(name, 0, nthreads, pri, minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1804 |
maxalloc, &p0, 0, flags | TASKQ_NOINSTANCE)); |
0 | 1805 |
} |
1806 |
||
1807 |
/* |
|
1808 |
* Create an instance of task queue. It is legal to create task queues with the |
|
1809 |
* same name and different instances. |
|
1810 |
* |
|
1811 |
* taskq_create_instance is used by ddi_taskq_create() where it gets the |
|
1812 |
* instance from ddi_get_instance(). In some cases the instance is not |
|
1813 |
* initialized and is set to -1. This case is handled as if no instance was |
|
1814 |
* passed at all. |
|
1815 |
*/ |
|
1816 |
taskq_t * |
|
1817 |
taskq_create_instance(const char *name, int instance, int nthreads, pri_t pri, |
|
1818 |
int minalloc, int maxalloc, uint_t flags) |
|
1819 |
{ |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1820 |
ASSERT((flags & ~TASKQ_INTERFACE_FLAGS) == 0); |
0 | 1821 |
ASSERT((instance >= 0) || (instance == -1)); |
1822 |
||
1823 |
if (instance < 0) { |
|
1824 |
flags |= TASKQ_NOINSTANCE; |
|
1825 |
} |
|
1826 |
||
1827 |
return (taskq_create_common(name, instance, nthreads, |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1828 |
pri, minalloc, maxalloc, &p0, 0, flags)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1829 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1830 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1831 |
taskq_t * |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1832 |
taskq_create_proc(const char *name, int nthreads, pri_t pri, int minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1833 |
int maxalloc, proc_t *proc, uint_t flags) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1834 |
{ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1835 |
ASSERT((flags & ~TASKQ_INTERFACE_FLAGS) == 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1836 |
ASSERT(proc->p_flag & SSYS); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1837 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1838 |
return (taskq_create_common(name, 0, nthreads, pri, minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1839 |
maxalloc, proc, 0, flags | TASKQ_NOINSTANCE)); |
0 | 1840 |
} |
1841 |
||
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1842 |
taskq_t * |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1843 |
taskq_create_sysdc(const char *name, int nthreads, int minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1844 |
int maxalloc, proc_t *proc, uint_t dc, uint_t flags) |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1845 |
{ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1846 |
ASSERT((flags & ~TASKQ_INTERFACE_FLAGS) == 0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1847 |
ASSERT(proc->p_flag & SSYS); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1848 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1849 |
return (taskq_create_common(name, 0, nthreads, minclsyspri, minalloc, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1850 |
maxalloc, proc, dc, flags | TASKQ_NOINSTANCE | TASKQ_DUTY_CYCLE)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1851 |
} |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1852 |
|
0 | 1853 |
static taskq_t * |
1854 |
taskq_create_common(const char *name, int instance, int nthreads, pri_t pri, |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1855 |
int minalloc, int maxalloc, proc_t *proc, uint_t dc, uint_t flags) |
0 | 1856 |
{ |
1857 |
taskq_t *tq = kmem_cache_alloc(taskq_cache, KM_SLEEP); |
|
1858 |
uint_t ncpus = ((boot_max_ncpus == -1) ? max_ncpus : boot_max_ncpus); |
|
1859 |
uint_t bsize; /* # of buckets - always power of 2 */ |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1860 |
int max_nthreads; |
0 | 1861 |
|
1862 |
/* |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1863 |
* TASKQ_DYNAMIC, TASKQ_CPR_SAFE and TASKQ_THREADS_CPU_PCT are all |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1864 |
* mutually incompatible. |
0 | 1865 |
*/ |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1866 |
IMPLY((flags & TASKQ_DYNAMIC), !(flags & TASKQ_CPR_SAFE)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1867 |
IMPLY((flags & TASKQ_DYNAMIC), !(flags & TASKQ_THREADS_CPU_PCT)); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1868 |
IMPLY((flags & TASKQ_CPR_SAFE), !(flags & TASKQ_THREADS_CPU_PCT)); |
0 | 1869 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1870 |
/* Cannot have DUTY_CYCLE without a non-p0 kernel process */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1871 |
IMPLY((flags & TASKQ_DUTY_CYCLE), proc != &p0); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1872 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1873 |
/* Cannot have DC_BATCH without DUTY_CYCLE */ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1874 |
ASSERT((flags & (TASKQ_DUTY_CYCLE|TASKQ_DC_BATCH)) != TASKQ_DC_BATCH); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1875 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1876 |
ASSERT(proc != NULL); |
0 | 1877 |
|
1878 |
bsize = 1 << (highbit(ncpus) - 1); |
|
1879 |
ASSERT(bsize >= 1); |
|
1880 |
bsize = MIN(bsize, taskq_maxbuckets); |
|
1881 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1882 |
if (flags & TASKQ_DYNAMIC) { |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1883 |
ASSERT3S(nthreads, >=, 1); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1884 |
tq->tq_maxsize = nthreads; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1885 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1886 |
/* For dynamic task queues use just one backup thread */ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1887 |
nthreads = max_nthreads = 1; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1888 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1889 |
} else if (flags & TASKQ_THREADS_CPU_PCT) { |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1890 |
uint_t pct; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1891 |
ASSERT3S(nthreads, >=, 0); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1892 |
pct = nthreads; |
0 | 1893 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1894 |
if (pct > taskq_cpupct_max_percent) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1895 |
pct = taskq_cpupct_max_percent; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1896 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1897 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1898 |
* If you're using THREADS_CPU_PCT, the process for the |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1899 |
* taskq threads must be curproc. This allows any pset |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1900 |
* binding to be inherited correctly. If proc is &p0, |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1901 |
* we won't be creating LWPs, so new threads will be assigned |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1902 |
* to the default processor set. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1903 |
*/ |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1904 |
ASSERT(curproc == proc || proc == &p0); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1905 |
tq->tq_threads_ncpus_pct = pct; |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1906 |
nthreads = 1; /* corrected in taskq_thread_create() */ |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1907 |
max_nthreads = TASKQ_THREADS_PCT(max_ncpus, pct); |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1908 |
|
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1909 |
} else { |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1910 |
ASSERT3S(nthreads, >=, 1); |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1911 |
max_nthreads = nthreads; |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1912 |
} |
0 | 1913 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1914 |
if (max_nthreads < taskq_minimum_nthreads_max) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1915 |
max_nthreads = taskq_minimum_nthreads_max; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1916 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1917 |
/* |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1918 |
* Make sure the name is 0-terminated, and conforms to the rules for |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1919 |
* C indentifiers |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1920 |
*/ |
0 | 1921 |
(void) strncpy(tq->tq_name, name, TASKQ_NAMELEN + 1); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1922 |
strident_canon(tq->tq_name, TASKQ_NAMELEN + 1); |
0 | 1923 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1924 |
tq->tq_flags = flags | TASKQ_CHANGING; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1925 |
tq->tq_active = 0; |
0 | 1926 |
tq->tq_instance = instance; |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1927 |
tq->tq_nthreads_target = nthreads; |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1928 |
tq->tq_nthreads_max = max_nthreads; |
0 | 1929 |
tq->tq_minalloc = minalloc; |
1930 |
tq->tq_maxalloc = maxalloc; |
|
1931 |
tq->tq_nbuckets = bsize; |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1932 |
tq->tq_proc = proc; |
0 | 1933 |
tq->tq_pri = pri; |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1934 |
tq->tq_DC = dc; |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1935 |
list_link_init(&tq->tq_cpupct_link); |
0 | 1936 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1937 |
if (max_nthreads > 1) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1938 |
tq->tq_threadlist = kmem_alloc( |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1939 |
sizeof (kthread_t *) * max_nthreads, KM_SLEEP); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1940 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1941 |
mutex_enter(&tq->tq_lock); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1942 |
if (flags & TASKQ_PREPOPULATE) { |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1943 |
while (minalloc-- > 0) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1944 |
taskq_ent_free(tq, taskq_ent_alloc(tq, TQ_SLEEP)); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1945 |
} |
0 | 1946 |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1947 |
/* |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1948 |
* Create the first thread, which will create any other threads |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1949 |
* necessary. taskq_thread_create will not return until we have |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1950 |
* enough threads to be able to process requests. |
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1951 |
*/ |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1952 |
taskq_thread_create(tq); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1953 |
mutex_exit(&tq->tq_lock); |
0 | 1954 |
|
1955 |
if (flags & TASKQ_DYNAMIC) { |
|
1956 |
taskq_bucket_t *bucket = kmem_zalloc(sizeof (taskq_bucket_t) * |
|
1957 |
bsize, KM_SLEEP); |
|
1958 |
int b_id; |
|
1959 |
||
1960 |
tq->tq_buckets = bucket; |
|
1961 |
||
1962 |
/* Initialize each bucket */ |
|
1963 |
for (b_id = 0; b_id < bsize; b_id++, bucket++) { |
|
1964 |
mutex_init(&bucket->tqbucket_lock, NULL, MUTEX_DEFAULT, |
|
1965 |
NULL); |
|
1966 |
cv_init(&bucket->tqbucket_cv, NULL, CV_DEFAULT, NULL); |
|
1967 |
bucket->tqbucket_taskq = tq; |
|
1968 |
bucket->tqbucket_freelist.tqent_next = |
|
1969 |
bucket->tqbucket_freelist.tqent_prev = |
|
1970 |
&bucket->tqbucket_freelist; |
|
1971 |
if (flags & TASKQ_PREPOPULATE) |
|
1972 |
taskq_bucket_extend(bucket); |
|
1973 |
} |
|
1974 |
} |
|
1975 |
||
1976 |
/* |
|
1977 |
* Install kstats. |
|
1978 |
* We have two cases: |
|
1979 |
* 1) Instance is provided to taskq_create_instance(). In this case it |
|
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
1980 |
* should be >= 0 and we use it. |
0 | 1981 |
* |
1982 |
* 2) Instance is not provided and is automatically generated |
|
1983 |
*/ |
|
1984 |
if (flags & TASKQ_NOINSTANCE) { |
|
1985 |
instance = tq->tq_instance = |
|
1986 |
(int)(uintptr_t)vmem_alloc(taskq_id_arena, 1, VM_SLEEP); |
|
1987 |
} |
|
1988 |
||
1989 |
if (flags & TASKQ_DYNAMIC) { |
|
1990 |
if ((tq->tq_kstat = kstat_create("unix", instance, |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1991 |
tq->tq_name, "taskq_d", KSTAT_TYPE_NAMED, |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1992 |
sizeof (taskq_d_kstat) / sizeof (kstat_named_t), |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
1993 |
KSTAT_FLAG_VIRTUAL)) != NULL) { |
0 | 1994 |
tq->tq_kstat->ks_lock = &taskq_d_kstat_lock; |
1995 |
tq->tq_kstat->ks_data = &taskq_d_kstat; |
|
1996 |
tq->tq_kstat->ks_update = taskq_d_kstat_update; |
|
1997 |
tq->tq_kstat->ks_private = tq; |
|
1998 |
kstat_install(tq->tq_kstat); |
|
1999 |
} |
|
2000 |
} else { |
|
2001 |
if ((tq->tq_kstat = kstat_create("unix", instance, tq->tq_name, |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2002 |
"taskq", KSTAT_TYPE_NAMED, |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2003 |
sizeof (taskq_kstat) / sizeof (kstat_named_t), |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2004 |
KSTAT_FLAG_VIRTUAL)) != NULL) { |
0 | 2005 |
tq->tq_kstat->ks_lock = &taskq_kstat_lock; |
2006 |
tq->tq_kstat->ks_data = &taskq_kstat; |
|
2007 |
tq->tq_kstat->ks_update = taskq_kstat_update; |
|
2008 |
tq->tq_kstat->ks_private = tq; |
|
2009 |
kstat_install(tq->tq_kstat); |
|
2010 |
} |
|
2011 |
} |
|
2012 |
||
2013 |
return (tq); |
|
2014 |
} |
|
2015 |
||
2016 |
/* |
|
2017 |
* taskq_destroy(). |
|
2018 |
* |
|
2019 |
* Assumes: by the time taskq_destroy is called no one will use this task queue |
|
2020 |
* in any way and no one will try to dispatch entries in it. |
|
2021 |
*/ |
|
2022 |
void |
|
2023 |
taskq_destroy(taskq_t *tq) |
|
2024 |
{ |
|
2025 |
taskq_bucket_t *b = tq->tq_buckets; |
|
2026 |
int bid = 0; |
|
2027 |
||
2028 |
ASSERT(! (tq->tq_flags & TASKQ_CPR_SAFE)); |
|
2029 |
||
2030 |
/* |
|
2031 |
* Destroy kstats. |
|
2032 |
*/ |
|
2033 |
if (tq->tq_kstat != NULL) { |
|
2034 |
kstat_delete(tq->tq_kstat); |
|
2035 |
tq->tq_kstat = NULL; |
|
2036 |
} |
|
2037 |
||
2038 |
/* |
|
2039 |
* Destroy instance if needed. |
|
2040 |
*/ |
|
2041 |
if (tq->tq_flags & TASKQ_NOINSTANCE) { |
|
2042 |
vmem_free(taskq_id_arena, (void *)(uintptr_t)(tq->tq_instance), |
|
2043 |
1); |
|
2044 |
tq->tq_instance = 0; |
|
2045 |
} |
|
2046 |
||
2047 |
/* |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2048 |
* Unregister from the cpupct list. |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2049 |
*/ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2050 |
if (tq->tq_flags & TASKQ_THREADS_CPU_PCT) { |
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
2051 |
taskq_cpupct_remove(tq); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2052 |
} |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2053 |
|
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2054 |
/* |
0 | 2055 |
* Wait for any pending entries to complete. |
2056 |
*/ |
|
2057 |
taskq_wait(tq); |
|
2058 |
||
2059 |
mutex_enter(&tq->tq_lock); |
|
2060 |
ASSERT((tq->tq_task.tqent_next == &tq->tq_task) && |
|
2061 |
(tq->tq_active == 0)); |
|
2062 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2063 |
/* notify all the threads that they need to exit */ |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2064 |
tq->tq_nthreads_target = 0; |
0 | 2065 |
|
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2066 |
tq->tq_flags |= TASKQ_CHANGING; |
0 | 2067 |
cv_broadcast(&tq->tq_dispatch_cv); |
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2068 |
cv_broadcast(&tq->tq_exit_cv); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2069 |
|
0 | 2070 |
while (tq->tq_nthreads != 0) |
2071 |
cv_wait(&tq->tq_wait_cv, &tq->tq_lock); |
|
2072 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2073 |
if (tq->tq_nthreads_max != 1) |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2074 |
kmem_free(tq->tq_threadlist, sizeof (kthread_t *) * |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2075 |
tq->tq_nthreads_max); |
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2076 |
|
0 | 2077 |
tq->tq_minalloc = 0; |
2078 |
while (tq->tq_nalloc != 0) |
|
2079 |
taskq_ent_free(tq, taskq_ent_alloc(tq, TQ_SLEEP)); |
|
2080 |
||
2081 |
mutex_exit(&tq->tq_lock); |
|
2082 |
||
2083 |
/* |
|
2084 |
* Mark each bucket as closing and wakeup all sleeping threads. |
|
2085 |
*/ |
|
2086 |
for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) { |
|
2087 |
taskq_ent_t *tqe; |
|
2088 |
||
2089 |
mutex_enter(&b->tqbucket_lock); |
|
2090 |
||
2091 |
b->tqbucket_flags |= TQBUCKET_CLOSE; |
|
2092 |
/* Wakeup all sleeping threads */ |
|
2093 |
||
2094 |
for (tqe = b->tqbucket_freelist.tqent_next; |
|
2095 |
tqe != &b->tqbucket_freelist; tqe = tqe->tqent_next) |
|
2096 |
cv_signal(&tqe->tqent_cv); |
|
2097 |
||
2098 |
ASSERT(b->tqbucket_nalloc == 0); |
|
2099 |
||
2100 |
/* |
|
2101 |
* At this point we waited for all pending jobs to complete (in |
|
2102 |
* both the task queue and the bucket and no new jobs should |
|
2103 |
* arrive. Wait for all threads to die. |
|
2104 |
*/ |
|
2105 |
while (b->tqbucket_nfree > 0) |
|
2106 |
cv_wait(&b->tqbucket_cv, &b->tqbucket_lock); |
|
2107 |
mutex_exit(&b->tqbucket_lock); |
|
2108 |
mutex_destroy(&b->tqbucket_lock); |
|
2109 |
cv_destroy(&b->tqbucket_cv); |
|
2110 |
} |
|
2111 |
||
2112 |
if (tq->tq_buckets != NULL) { |
|
2113 |
ASSERT(tq->tq_flags & TASKQ_DYNAMIC); |
|
2114 |
kmem_free(tq->tq_buckets, |
|
2115 |
sizeof (taskq_bucket_t) * tq->tq_nbuckets); |
|
2116 |
||
2117 |
/* Cleanup fields before returning tq to the cache */ |
|
2118 |
tq->tq_buckets = NULL; |
|
2119 |
tq->tq_tcreates = 0; |
|
2120 |
tq->tq_tdeaths = 0; |
|
2121 |
} else { |
|
2122 |
ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC)); |
|
2123 |
} |
|
2124 |
||
9515
d3b739d9d043
6586537 async zio taskqs can block out userland commands
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
0
diff
changeset
|
2125 |
tq->tq_threads_ncpus_pct = 0; |
0 | 2126 |
tq->tq_totaltime = 0; |
2127 |
tq->tq_tasks = 0; |
|
2128 |
tq->tq_maxtasks = 0; |
|
2129 |
tq->tq_executed = 0; |
|
2130 |
kmem_cache_free(taskq_cache, tq); |
|
2131 |
} |
|
2132 |
||
2133 |
/* |
|
2134 |
* Extend a bucket with a new entry on the free list and attach a worker thread |
|
2135 |
* to it. |
|
2136 |
* |
|
2137 |
* Argument: pointer to the bucket. |
|
2138 |
* |
|
2139 |
* This function may quietly fail. It is only used by taskq_dispatch() which |
|
2140 |
* handles such failures properly. |
|
2141 |
*/ |
|
2142 |
static void |
|
2143 |
taskq_bucket_extend(void *arg) |
|
2144 |
{ |
|
2145 |
taskq_ent_t *tqe; |
|
2146 |
taskq_bucket_t *b = (taskq_bucket_t *)arg; |
|
2147 |
taskq_t *tq = b->tqbucket_taskq; |
|
2148 |
int nthreads; |
|
2149 |
||
2150 |
if (! ENOUGH_MEMORY()) { |
|
2151 |
TQ_STAT(b, tqs_nomem); |
|
2152 |
return; |
|
2153 |
} |
|
2154 |
||
2155 |
mutex_enter(&tq->tq_lock); |
|
2156 |
||
2157 |
/* |
|
2158 |
* Observe global taskq limits on the number of threads. |
|
2159 |
*/ |
|
2160 |
if (tq->tq_tcreates++ - tq->tq_tdeaths > tq->tq_maxsize) { |
|
2161 |
tq->tq_tcreates--; |
|
2162 |
mutex_exit(&tq->tq_lock); |
|
2163 |
return; |
|
2164 |
} |
|
2165 |
mutex_exit(&tq->tq_lock); |
|
2166 |
||
2167 |
tqe = kmem_cache_alloc(taskq_ent_cache, KM_NOSLEEP); |
|
2168 |
||
2169 |
if (tqe == NULL) { |
|
2170 |
mutex_enter(&tq->tq_lock); |
|
2171 |
TQ_STAT(b, tqs_nomem); |
|
2172 |
tq->tq_tcreates--; |
|
2173 |
mutex_exit(&tq->tq_lock); |
|
2174 |
return; |
|
2175 |
} |
|
2176 |
||
2177 |
ASSERT(tqe->tqent_thread == NULL); |
|
2178 |
||
13414
b42c1f0432b6
734 taskq_dispatch_prealloc() desired
Garrett D'Amore <garrett@nexenta.com>
parents:
11854
diff
changeset
|
2179 |
tqe->tqent_un.tqent_bucket = b; |
0 | 2180 |
|
2181 |
/* |
|
2182 |
* Create a thread in a TS_STOPPED state first. If it is successfully |
|
2183 |
* created, place the entry on the free list and start the thread. |
|
2184 |
*/ |
|
2185 |
tqe->tqent_thread = thread_create(NULL, 0, taskq_d_thread, tqe, |
|
2186 |
0, &p0, TS_STOPPED, tq->tq_pri); |
|
2187 |
||
2188 |
/* |
|
2189 |
* Once the entry is ready, link it to the the bucket free list. |
|
2190 |
*/ |
|
2191 |
mutex_enter(&b->tqbucket_lock); |
|
2192 |
tqe->tqent_func = NULL; |
|
2193 |
TQ_APPEND(b->tqbucket_freelist, tqe); |
|
2194 |
b->tqbucket_nfree++; |
|
2195 |
TQ_STAT(b, tqs_tcreates); |
|
2196 |
||
2197 |
#if TASKQ_STATISTIC |
|
2198 |
nthreads = b->tqbucket_stat.tqs_tcreates - |
|
2199 |
b->tqbucket_stat.tqs_tdeaths; |
|
2200 |
b->tqbucket_stat.tqs_maxthreads = MAX(nthreads, |
|
2201 |
b->tqbucket_stat.tqs_maxthreads); |
|
2202 |
#endif |
|
2203 |
||
2204 |
mutex_exit(&b->tqbucket_lock); |
|
2205 |
/* |
|
2206 |
* Start the stopped thread. |
|
2207 |
*/ |
|
2208 |
thread_lock(tqe->tqent_thread); |
|
2209 |
tqe->tqent_thread->t_taskq = tq; |
|
2210 |
tqe->tqent_thread->t_schedflag |= TS_ALLSTART; |
|
2211 |
setrun_locked(tqe->tqent_thread); |
|
2212 |
thread_unlock(tqe->tqent_thread); |
|
2213 |
} |
|
2214 |
||
2215 |
static int |
|
2216 |
taskq_kstat_update(kstat_t *ksp, int rw) |
|
2217 |
{ |
|
2218 |
struct taskq_kstat *tqsp = &taskq_kstat; |
|
2219 |
taskq_t *tq = ksp->ks_private; |
|
2220 |
||
2221 |
if (rw == KSTAT_WRITE) |
|
2222 |
return (EACCES); |
|
2223 |
||
11173
87f3734e64df
6881015 ZFS write activity prevents other threads from running in a timely manner
Jonathan Adams <Jonathan.Adams@Sun.COM>
parents:
11066
diff
changeset
|
2224 |
tqsp->tq_pid.value.ui64 = tq->tq_proc->p_pid; |
0 | 2225 |
tqsp->tq_tasks.value.ui64 = tq->tq_tasks; |
2226 |
tqsp->tq_executed.value.ui64 = tq->tq_executed; |
|
2227 |
tqsp->tq_maxtasks.value.ui64 = tq->tq_maxtasks; |
|
2228 |
tqsp->tq_totaltime.value.ui64 = tq->tq_totaltime; |
|
2229 |
tqsp->tq_nactive.value.ui64 = tq->tq_active; |
|
2230 |
tqsp->tq_nalloc.value.ui64 = tq->tq_nalloc; |
|
2231 |
tqsp->tq_pri.value.ui64 = tq->tq_pri; |
|
2232 |
tqsp->tq_nthreads.value.ui64 = tq->tq_nthreads; |
|
2233 |
return (0); |
|
2234 |
} |
|
2235 |
||
2236 |
static int |
|
2237 |
taskq_d_kstat_update(kstat_t *ksp, int rw) |
|
2238 |
{ |
|
2239 |
struct taskq_d_kstat *tqsp = &taskq_d_kstat; |
|
2240 |
taskq_t *tq = ksp->ks_private; |
|
2241 |
taskq_bucket_t *b = tq->tq_buckets; |
|
2242 |
int bid = 0; |
|
2243 |
||
2244 |
if (rw == KSTAT_WRITE) |
|
2245 |
return (EACCES); |
|
2246 |
||
2247 |
ASSERT(tq->tq_flags & TASKQ_DYNAMIC); |
|
2248 |
||
2249 |
tqsp->tqd_btasks.value.ui64 = tq->tq_tasks; |
|
2250 |
tqsp->tqd_bexecuted.value.ui64 = tq->tq_executed; |
|
2251 |
tqsp->tqd_bmaxtasks.value.ui64 = tq->tq_maxtasks; |
|
2252 |
tqsp->tqd_bnalloc.value.ui64 = tq->tq_nalloc; |
|
2253 |
tqsp->tqd_bnactive.value.ui64 = tq->tq_active; |
|
2254 |
tqsp->tqd_btotaltime.value.ui64 = tq->tq_totaltime; |
|
2255 |
tqsp->tqd_pri.value.ui64 = tq->tq_pri; |
|
2256 |
||
2257 |
tqsp->tqd_hits.value.ui64 = 0; |
|
2258 |
tqsp->tqd_misses.value.ui64 = 0; |
|
2259 |
tqsp->tqd_overflows.value.ui64 = 0; |
|
2260 |
tqsp->tqd_tcreates.value.ui64 = 0; |
|
2261 |
tqsp->tqd_tdeaths.value.ui64 = 0; |
|
2262 |
tqsp->tqd_maxthreads.value.ui64 = 0; |
|
2263 |
tqsp->tqd_nomem.value.ui64 = 0; |
|
2264 |
tqsp->tqd_disptcreates.value.ui64 = 0; |
|
2265 |
tqsp->tqd_totaltime.value.ui64 = 0; |
|
2266 |
tqsp->tqd_nalloc.value.ui64 = 0; |
|
2267 |
tqsp->tqd_nfree.value.ui64 = 0; |
|
2268 |
||
2269 |
for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) { |
|
2270 |
tqsp->tqd_hits.value.ui64 += b->tqbucket_stat.tqs_hits; |
|
2271 |
tqsp->tqd_misses.value.ui64 += b->tqbucket_stat.tqs_misses; |
|
2272 |
tqsp->tqd_overflows.value.ui64 += b->tqbucket_stat.tqs_overflow; |
|
2273 |
tqsp->tqd_tcreates.value.ui64 += b->tqbucket_stat.tqs_tcreates; |
|
2274 |
tqsp->tqd_tdeaths.value.ui64 += b->tqbucket_stat.tqs_tdeaths; |
|
2275 |
tqsp->tqd_maxthreads.value.ui64 += |
|
2276 |
b->tqbucket_stat.tqs_maxthreads; |
|
2277 |
tqsp->tqd_nomem.value.ui64 += b->tqbucket_stat.tqs_nomem; |
|
2278 |
tqsp->tqd_disptcreates.value.ui64 += |
|
2279 |
b->tqbucket_stat.tqs_disptcreates; |
|
2280 |
tqsp->tqd_totaltime.value.ui64 += b->tqbucket_totaltime; |
|
2281 |
tqsp->tqd_nalloc.value.ui64 += b->tqbucket_nalloc; |
|
2282 |
tqsp->tqd_nfree.value.ui64 += b->tqbucket_nfree; |
|
2283 |
} |
|
2284 |
return (0); |
|
2285 |
} |