9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
27 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
28 * Copyright (c) 2014 by Delphix. All rights reserved.
29 */
30
31 #include <sys/zfs_context.h>
32
33 int taskq_now;
34 taskq_t *system_taskq;
35
36 #define TASKQ_ACTIVE 0x00010000
37 #define TASKQ_NAMELEN 31
38
39 struct taskq {
40 char tq_name[TASKQ_NAMELEN + 1];
41 kmutex_t tq_lock;
42 krwlock_t tq_threadlock;
43 kcondvar_t tq_dispatch_cv;
44 kcondvar_t tq_wait_cv;
45 thread_t *tq_threadlist;
46 int tq_flags;
47 int tq_active;
48 int tq_nthreads;
161 /*
162 * Enqueue the task to the underlying queue.
163 */
164 mutex_enter(&tq->tq_lock);
165
166 if (flags & TQ_FRONT) {
167 t->tqent_next = tq->tq_task.tqent_next;
168 t->tqent_prev = &tq->tq_task;
169 } else {
170 t->tqent_next = &tq->tq_task;
171 t->tqent_prev = tq->tq_task.tqent_prev;
172 }
173 t->tqent_next->tqent_prev = t;
174 t->tqent_prev->tqent_next = t;
175 t->tqent_func = func;
176 t->tqent_arg = arg;
177 cv_signal(&tq->tq_dispatch_cv);
178 mutex_exit(&tq->tq_lock);
179 }
180
181 void
182 taskq_wait(taskq_t *tq)
183 {
184 mutex_enter(&tq->tq_lock);
185 while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
186 cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
187 mutex_exit(&tq->tq_lock);
188 }
189
190 static void *
191 taskq_thread(void *arg)
192 {
193 taskq_t *tq = arg;
194 taskq_ent_t *t;
195 boolean_t prealloc;
196
197 mutex_enter(&tq->tq_lock);
198 while (tq->tq_flags & TASKQ_ACTIVE) {
199 if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
200 if (--tq->tq_active == 0)
|
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
27 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
28 * Copyright (c) 2014 by Delphix. All rights reserved.
29 * Copyright (c) 2017, Joyent, Inc.
30 */
31
32 #include <sys/zfs_context.h>
33
34 int taskq_now;
35 taskq_t *system_taskq;
36
37 #define TASKQ_ACTIVE 0x00010000
38 #define TASKQ_NAMELEN 31
39
40 struct taskq {
41 char tq_name[TASKQ_NAMELEN + 1];
42 kmutex_t tq_lock;
43 krwlock_t tq_threadlock;
44 kcondvar_t tq_dispatch_cv;
45 kcondvar_t tq_wait_cv;
46 thread_t *tq_threadlist;
47 int tq_flags;
48 int tq_active;
49 int tq_nthreads;
162 /*
163 * Enqueue the task to the underlying queue.
164 */
165 mutex_enter(&tq->tq_lock);
166
167 if (flags & TQ_FRONT) {
168 t->tqent_next = tq->tq_task.tqent_next;
169 t->tqent_prev = &tq->tq_task;
170 } else {
171 t->tqent_next = &tq->tq_task;
172 t->tqent_prev = tq->tq_task.tqent_prev;
173 }
174 t->tqent_next->tqent_prev = t;
175 t->tqent_prev->tqent_next = t;
176 t->tqent_func = func;
177 t->tqent_arg = arg;
178 cv_signal(&tq->tq_dispatch_cv);
179 mutex_exit(&tq->tq_lock);
180 }
181
182 boolean_t
183 taskq_empty(taskq_t *tq)
184 {
185 boolean_t rv;
186
187 mutex_enter(&tq->tq_lock);
188 rv = (tq->tq_task.tqent_next == &tq->tq_task) && (tq->tq_active == 0);
189 mutex_exit(&tq->tq_lock);
190
191 return (rv);
192 }
193
194 void
195 taskq_wait(taskq_t *tq)
196 {
197 mutex_enter(&tq->tq_lock);
198 while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
199 cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
200 mutex_exit(&tq->tq_lock);
201 }
202
203 static void *
204 taskq_thread(void *arg)
205 {
206 taskq_t *tq = arg;
207 taskq_ent_t *t;
208 boolean_t prealloc;
209
210 mutex_enter(&tq->tq_lock);
211 while (tq->tq_flags & TASKQ_ACTIVE) {
212 if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
213 if (--tq->tq_active == 0)
|