]> git.proxmox.com Git - mirror_spl.git/blame - module/splat/splat-taskq.c
Add 3 missing typedefs.
[mirror_spl.git] / module / splat / splat-taskq.c
CommitLineData
715f6251 1/*
2 * This file is part of the SPL: Solaris Porting Layer.
3 *
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
6 * Written by:
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
10 * UCRL-CODE-235197
11 *
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 */
26
7c50328b 27#include "splat-internal.h"
f1ca4da6 28
7c50328b 29#define SPLAT_TASKQ_NAME "taskq"
30#define SPLAT_TASKQ_DESC "Kernel Task Queue Tests"
f1ca4da6 31
7c50328b 32#define SPLAT_TASKQ_TEST1_ID 0x0201
33#define SPLAT_TASKQ_TEST1_NAME "single"
34#define SPLAT_TASKQ_TEST1_DESC "Single task queue, single task"
f1ca4da6 35
5562e5d1 36#define SPLAT_TASKQ_TEST2_ID 0x0202
7c50328b 37#define SPLAT_TASKQ_TEST2_NAME "multiple"
38#define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
f1ca4da6 39
5562e5d1 40#define SPLAT_TASKQ_TEST3_ID 0x0203
e9cb2b4f
BB
41#define SPLAT_TASKQ_TEST3_NAME "system"
42#define SPLAT_TASKQ_TEST3_DESC "System task queue, multiple tasks"
43
5562e5d1 44#define SPLAT_TASKQ_TEST4_ID 0x0204
7257ec41
BB
45#define SPLAT_TASKQ_TEST4_NAME "wait"
46#define SPLAT_TASKQ_TEST4_DESC "Multiple task waiting"
47
5562e5d1
BB
48#define SPLAT_TASKQ_TEST5_ID 0x0205
49#define SPLAT_TASKQ_TEST5_NAME "order"
50#define SPLAT_TASKQ_TEST5_DESC "Correct task ordering"
51
52#define SPLAT_TASKQ_ORDER_MAX 8
53
7c50328b 54typedef struct splat_taskq_arg {
f1ca4da6 55 int flag;
56 int id;
7257ec41 57 atomic_t count;
5562e5d1
BB
58 int order[SPLAT_TASKQ_ORDER_MAX];
59 spinlock_t lock;
f1ca4da6 60 struct file *file;
61 const char *name;
7c50328b 62} splat_taskq_arg_t;
f1ca4da6 63
5562e5d1
BB
64typedef struct splat_taskq_id {
65 int id;
66 splat_taskq_arg_t *arg;
67} splat_taskq_id_t;
68
69/*
70 * Create a taskq, queue a task, wait until task completes, ensure
71 * task ran properly, cleanup taskq.
f1ca4da6 72 */
73static void
e9cb2b4f 74splat_taskq_test13_func(void *arg)
f1ca4da6 75{
7c50328b 76 splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
f1ca4da6 77
78 ASSERT(tq_arg);
7c50328b 79 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME,
f1ca4da6 80 "Taskq '%s' function '%s' setting flag\n",
e9cb2b4f 81 tq_arg->name, sym2str(splat_taskq_test13_func));
f1ca4da6 82 tq_arg->flag = 1;
83}
84
85static int
7c50328b 86splat_taskq_test1(struct file *file, void *arg)
f1ca4da6 87{
88 taskq_t *tq;
89 taskqid_t id;
7c50328b 90 splat_taskq_arg_t tq_arg;
f1ca4da6 91
7c50328b 92 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' creating\n",
93 SPLAT_TASKQ_TEST1_NAME);
bcd68186 94 if ((tq = taskq_create(SPLAT_TASKQ_TEST1_NAME, 1, maxclsyspri,
95 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
7c50328b 96 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
f1ca4da6 97 "Taskq '%s' create failed\n",
7c50328b 98 SPLAT_TASKQ_TEST1_NAME);
f1ca4da6 99 return -EINVAL;
100 }
101
102 tq_arg.flag = 0;
103 tq_arg.id = 0;
104 tq_arg.file = file;
7c50328b 105 tq_arg.name = SPLAT_TASKQ_TEST1_NAME;
f1ca4da6 106
7c50328b 107 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
f1ca4da6 108 "Taskq '%s' function '%s' dispatching\n",
e9cb2b4f
BB
109 tq_arg.name, sym2str(splat_taskq_test13_func));
110 if ((id = taskq_dispatch(tq, splat_taskq_test13_func,
bcd68186 111 &tq_arg, TQ_SLEEP)) == 0) {
7c50328b 112 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
f1ca4da6 113 "Taskq '%s' function '%s' dispatch failed\n",
e9cb2b4f 114 tq_arg.name, sym2str(splat_taskq_test13_func));
4098c921 115 taskq_destroy(tq);
f1ca4da6 116 return -EINVAL;
117 }
118
7c50328b 119 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' waiting\n",
f1ca4da6 120 tq_arg.name);
121 taskq_wait(tq);
7c50328b 122 splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' destroying\n",
f1ca4da6 123 tq_arg.name);
4098c921 124 taskq_destroy(tq);
f1ca4da6 125
126 return (tq_arg.flag) ? 0 : -EINVAL;
127}
128
5562e5d1
BB
129/*
130 * Create multiple taskq's, each with multiple tasks, wait until
131 * all tasks complete, ensure all tasks ran properly and in the
132 * correct order. Run order must be the same as the order submitted
133 * because we only have 1 thread per taskq. Finally cleanup the taskq.
f1ca4da6 134 */
135static void
7c50328b 136splat_taskq_test2_func1(void *arg)
f1ca4da6 137{
7c50328b 138 splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
f1ca4da6 139
140 ASSERT(tq_arg);
7c50328b 141 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 142 "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
143 tq_arg->name, tq_arg->id,
7c50328b 144 sym2str(splat_taskq_test2_func1),
f1ca4da6 145 tq_arg->flag * 2, tq_arg->flag);
146 tq_arg->flag *= 2;
147}
148
149static void
7c50328b 150splat_taskq_test2_func2(void *arg)
f1ca4da6 151{
7c50328b 152 splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
f1ca4da6 153
154 ASSERT(tq_arg);
7c50328b 155 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 156 "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
157 tq_arg->name, tq_arg->id,
7c50328b 158 sym2str(splat_taskq_test2_func2),
f1ca4da6 159 tq_arg->flag + 1, tq_arg->flag);
160 tq_arg->flag += 1;
161}
162
163#define TEST2_TASKQS 8
5562e5d1 164#define TEST2_THREADS_PER_TASKQ 1
bcd68186 165
f1ca4da6 166static int
7c50328b 167splat_taskq_test2(struct file *file, void *arg) {
f1ca4da6 168 taskq_t *tq[TEST2_TASKQS] = { NULL };
169 taskqid_t id;
7c50328b 170 splat_taskq_arg_t tq_args[TEST2_TASKQS];
f1ca4da6 171 int i, rc = 0;
172
173 for (i = 0; i < TEST2_TASKQS; i++) {
174
7c50328b 175 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' "
176 "creating\n", SPLAT_TASKQ_TEST2_NAME, i);
177 if ((tq[i] = taskq_create(SPLAT_TASKQ_TEST2_NAME,
bcd68186 178 TEST2_THREADS_PER_TASKQ,
179 maxclsyspri, 50, INT_MAX,
180 TASKQ_PREPOPULATE)) == NULL) {
7c50328b 181 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 182 "Taskq '%s/%d' create failed\n",
7c50328b 183 SPLAT_TASKQ_TEST2_NAME, i);
f1ca4da6 184 rc = -EINVAL;
185 break;
186 }
187
188 tq_args[i].flag = i;
189 tq_args[i].id = i;
190 tq_args[i].file = file;
7c50328b 191 tq_args[i].name = SPLAT_TASKQ_TEST2_NAME;
f1ca4da6 192
7c50328b 193 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 194 "Taskq '%s/%d' function '%s' dispatching\n",
7c50328b 195 tq_args[i].name, tq_args[i].id,
196 sym2str(splat_taskq_test2_func1));
f1ca4da6 197 if ((id = taskq_dispatch(
bcd68186 198 tq[i], splat_taskq_test2_func1,
199 &tq_args[i], TQ_SLEEP)) == 0) {
7c50328b 200 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 201 "Taskq '%s/%d' function '%s' dispatch "
202 "failed\n", tq_args[i].name, tq_args[i].id,
7c50328b 203 sym2str(splat_taskq_test2_func1));
f1ca4da6 204 rc = -EINVAL;
205 break;
206 }
207
7c50328b 208 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 209 "Taskq '%s/%d' function '%s' dispatching\n",
7c50328b 210 tq_args[i].name, tq_args[i].id,
211 sym2str(splat_taskq_test2_func2));
f1ca4da6 212 if ((id = taskq_dispatch(
bcd68186 213 tq[i], splat_taskq_test2_func2,
214 &tq_args[i], TQ_SLEEP)) == 0) {
7c50328b 215 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 216 "Taskq '%s/%d' function '%s' dispatch failed\n",
217 tq_args[i].name, tq_args[i].id,
7c50328b 218 sym2str(splat_taskq_test2_func2));
f1ca4da6 219 rc = -EINVAL;
220 break;
221 }
222 }
223
224 /* When rc is set we're effectively just doing cleanup here, so
225 * ignore new errors in that case. They just cause noise. */
226 for (i = 0; i < TEST2_TASKQS; i++) {
227 if (tq[i] != NULL) {
7c50328b 228 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 229 "Taskq '%s/%d' waiting\n",
230 tq_args[i].name, tq_args[i].id);
231 taskq_wait(tq[i]);
7c50328b 232 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 233 "Taskq '%s/%d; destroying\n",
234 tq_args[i].name, tq_args[i].id);
4098c921 235 taskq_destroy(tq[i]);
f1ca4da6 236
237 if (!rc && tq_args[i].flag != ((i * 2) + 1)) {
7c50328b 238 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 239 "Taskq '%s/%d' processed tasks "
240 "out of order; %d != %d\n",
241 tq_args[i].name, tq_args[i].id,
242 tq_args[i].flag, i * 2 + 1);
243 rc = -EINVAL;
244 } else {
7c50328b 245 splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
f1ca4da6 246 "Taskq '%s/%d' processed tasks "
247 "in the correct order; %d == %d\n",
248 tq_args[i].name, tq_args[i].id,
249 tq_args[i].flag, i * 2 + 1);
250 }
251 }
252 }
253
254 return rc;
255}
256
5562e5d1
BB
257/*
258 * Use the global system task queue with a single task, wait until task
259 * completes, ensure task ran properly.
e9cb2b4f
BB
260 */
261static int
262splat_taskq_test3(struct file *file, void *arg)
263{
264 taskqid_t id;
265 splat_taskq_arg_t tq_arg;
266
267 tq_arg.flag = 0;
268 tq_arg.id = 0;
269 tq_arg.file = file;
270 tq_arg.name = SPLAT_TASKQ_TEST3_NAME;
271
272 splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
273 "Taskq '%s' function '%s' dispatching\n",
274 tq_arg.name, sym2str(splat_taskq_test13_func));
275 if ((id = taskq_dispatch(system_taskq, splat_taskq_test13_func,
276 &tq_arg, TQ_SLEEP)) == 0) {
277 splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
278 "Taskq '%s' function '%s' dispatch failed\n",
279 tq_arg.name, sym2str(splat_taskq_test13_func));
280 return -EINVAL;
281 }
282
283 splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n",
284 tq_arg.name);
285 taskq_wait(system_taskq);
286
287 return (tq_arg.flag) ? 0 : -EINVAL;
288}
289
5562e5d1
BB
290/*
291 * Create a taskq and dispatch a large number of tasks to the queue.
292 * Then use taskq_wait() to block until all the tasks complete, then
293 * cross check that all the tasks ran by checking tg_arg->count which
294 * is incremented in the task function. Finally cleanup the taskq.
295 */
7257ec41
BB
296static void
297splat_taskq_test4_func(void *arg)
298{
299 splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
300 ASSERT(tq_arg);
301
302 atomic_inc(&tq_arg->count);
303}
304
305static int
306splat_taskq_test4(struct file *file, void *arg)
307{
308 taskq_t *tq;
309 splat_taskq_arg_t tq_arg;
310 int i, j, rc = 0;
311
312 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' creating\n",
313 SPLAT_TASKQ_TEST4_NAME);
314 if ((tq = taskq_create(SPLAT_TASKQ_TEST4_NAME, 1, maxclsyspri,
315 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
316 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
317 "Taskq '%s' create failed\n",
318 SPLAT_TASKQ_TEST4_NAME);
319 return -EINVAL;
320 }
321
322 tq_arg.file = file;
323 tq_arg.name = SPLAT_TASKQ_TEST4_NAME;
324
325 for (i = 1; i <= 1024; i *= 2) {
326 atomic_set(&tq_arg.count, 0);
327 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
328 "Taskq '%s' function '%s' dispatched %d times\n",
329 tq_arg.name, sym2str(splat_taskq_test4_func), i);
330
331 for (j = 0; j < i; j++) {
332 if ((taskq_dispatch(tq, splat_taskq_test4_func,
333 &tq_arg, TQ_SLEEP)) == 0) {
334 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
335 "Taskq '%s' function '%s' dispatch "
336 "%d failed\n", tq_arg.name,
337 sym2str(splat_taskq_test13_func), j);
338 rc = -EINVAL;
339 goto out;
340 }
341 }
342
343 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' "
344 "waiting for %d dispatches\n", tq_arg.name, i);
345 taskq_wait(tq);
346 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' "
347 "%d/%d dispatches finished\n", tq_arg.name,
348 atomic_read(&tq_arg.count), i);
349 if (atomic_read(&tq_arg.count) != i) {
350 rc = -ERANGE;
351 goto out;
352
353 }
354 }
355out:
356 splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' destroying\n",
357 tq_arg.name);
358 taskq_destroy(tq);
359
360 return rc;
361}
362
5562e5d1
BB
363/*
364 * Create a taskq and dispatch a specific sequence of tasks carefully
365 * crafted to validate the order in which tasks are processed. When
366 * there are multiple worker threads each thread will process the
367 * next pending task as soon as it completes its current task. This
368 * means that tasks do not strictly complete in order in which they
369 * were dispatched (increasing task id). This is fine but we need to
370 * verify that taskq_wait_id() blocks until the passed task id and all
371 * lower task ids complete. We do this by dispatching the following
372 * specific sequence of tasks each of which block for N time units.
373 * We then use taskq_wait_id() to unblock at specific task id and
374 * verify the only the expected task ids have completed and in the
375 * correct order. The two cases of interest are:
376 *
377 * 1) Task ids larger than the waited for task id can run and
378 * complete as long as there is an available worker thread.
379 * 2) All task ids lower than the waited one must complete before
380 * unblocking even if the waited task id itself has completed.
381 *
382 * The following table shows each task id and how they will be
383 * scheduled. Each rows represent one time unit and each column
384 * one of the three worker threads. The places taskq_wait_id()
385 * must unblock for a specific id are identified as well as the
386 * task ids which must have completed and their order.
387 *
388 * +-----+ <--- taskq_wait_id(tq, 8) unblocks
389 * | | Required Completion Order: 1,2,4,5,3
390 * +-----+ |
391 * | | |
392 * | | +-----+
393 * | | | 8 |
394 * | | +-----+ <--- taskq_wait_id(tq, 3) unblocks
395 * | | 7 | | Required Completion Order: 1,2,4,5,3,8,6,7
396 * | +-----+ |
397 * | 6 | | |
398 * +-----+ | |
399 * | | 5 | |
400 * | +-----+ |
401 * | 4 | | |
402 * +-----+ | |
403 * | 1 | 2 | 3 |
404 * +-----+-----+-----+
405 *
406 */
407static void
408splat_taskq_test5_func(void *arg)
409{
410 splat_taskq_id_t *tq_id = (splat_taskq_id_t *)arg;
411 splat_taskq_arg_t *tq_arg = tq_id->arg;
412 int factor;
413
414 /* Delays determined by above table */
415 switch (tq_id->id) {
416 default: factor = 0; break;
417 case 1: case 8: factor = 1; break;
418 case 2: case 4: case 5: factor = 2; break;
419 case 6: case 7: factor = 4; break;
420 case 3: factor = 5; break;
421 }
422
423 msleep(factor * 100);
424 splat_vprint(tq_arg->file, tq_arg->name,
425 "Taskqid %d complete for taskq '%s'\n",
426 tq_id->id, tq_arg->name);
427
428 spin_lock(&tq_arg->lock);
429 tq_arg->order[tq_arg->flag] = tq_id->id;
430 tq_arg->flag++;
431 spin_unlock(&tq_arg->lock);
432}
433
434static int
435splat_taskq_test5_order(splat_taskq_arg_t *tq_arg, int *order)
436{
437 int i, j;
438
439 for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) {
440 if (tq_arg->order[i] != order[i]) {
441 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST5_NAME,
442 "Taskq '%s' incorrect completion "
443 "order\n", tq_arg->name);
444 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST5_NAME,
445 "%s", "Expected { ");
446
447 for (j = 0; j < SPLAT_TASKQ_ORDER_MAX; j++)
448 splat_print(tq_arg->file, "%d ", order[j]);
449
450 splat_print(tq_arg->file, "%s", "}\n");
451 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST5_NAME,
452 "%s", "Got { ");
453
454 for (j = 0; j < SPLAT_TASKQ_ORDER_MAX; j++)
455 splat_print(tq_arg->file, "%d ",
456 tq_arg->order[j]);
457
458 splat_print(tq_arg->file, "%s", "}\n");
459 return -EILSEQ;
460 }
461 }
462
463 splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST5_NAME,
464 "Taskq '%s' validated correct completion order\n",
465 tq_arg->name);
466
467 return 0;
468}
469
470static int
471splat_taskq_test5(struct file *file, void *arg)
472{
473 taskq_t *tq;
474 taskqid_t id;
475 splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX];
476 splat_taskq_arg_t tq_arg;
477 int order1[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,0,0,0 };
478 int order2[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,8,6,7 };
479 int i, rc = 0;
480
481 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' creating\n",
482 SPLAT_TASKQ_TEST5_NAME);
483 if ((tq = taskq_create(SPLAT_TASKQ_TEST5_NAME, 3, maxclsyspri,
484 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
485 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
486 "Taskq '%s' create failed\n",
487 SPLAT_TASKQ_TEST5_NAME);
488 return -EINVAL;
489 }
490
491 tq_arg.flag = 0;
492 memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX);
493 spin_lock_init(&tq_arg.lock);
494 tq_arg.file = file;
495 tq_arg.name = SPLAT_TASKQ_TEST5_NAME;
496
497 for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) {
498 tq_id[i].id = i + 1;
499 tq_id[i].arg = &tq_arg;
500
501 if ((id = taskq_dispatch(tq, splat_taskq_test5_func,
502 &tq_id[i], TQ_SLEEP)) == 0) {
503 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
504 "Taskq '%s' function '%s' dispatch failed\n",
505 tq_arg.name, sym2str(splat_taskq_test5_func));
506 rc = -EINVAL;
507 goto out;
508 }
509
510 if (tq_id[i].id != id) {
511 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
512 "Taskq '%s' expected taskqid %d got %d\n",
513 tq_arg.name, (int)tq_id[i].id, (int)id);
514 rc = -EINVAL;
515 goto out;
516 }
517 }
518
519 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' "
520 "waiting for taskqid %d completion\n", tq_arg.name, 3);
521 taskq_wait_id(tq, 3);
522 if ((rc = splat_taskq_test5_order(&tq_arg, order1)))
523 goto out;
524
525 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' "
526 "waiting for taskqid %d completion\n", tq_arg.name, 8);
527 taskq_wait_id(tq, 8);
528 rc = splat_taskq_test5_order(&tq_arg, order2);
529
530out:
531 splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
532 "Taskq '%s' destroying\n", tq_arg.name);
533 taskq_destroy(tq);
534
535 return rc;
536}
537
7c50328b 538splat_subsystem_t *
539splat_taskq_init(void)
f1ca4da6 540{
7c50328b 541 splat_subsystem_t *sub;
f1ca4da6 542
543 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
544 if (sub == NULL)
545 return NULL;
546
547 memset(sub, 0, sizeof(*sub));
7c50328b 548 strncpy(sub->desc.name, SPLAT_TASKQ_NAME, SPLAT_NAME_SIZE);
549 strncpy(sub->desc.desc, SPLAT_TASKQ_DESC, SPLAT_DESC_SIZE);
f1ca4da6 550 INIT_LIST_HEAD(&sub->subsystem_list);
551 INIT_LIST_HEAD(&sub->test_list);
552 spin_lock_init(&sub->test_lock);
7c50328b 553 sub->desc.id = SPLAT_SUBSYSTEM_TASKQ;
f1ca4da6 554
7c50328b 555 SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST1_NAME, SPLAT_TASKQ_TEST1_DESC,
556 SPLAT_TASKQ_TEST1_ID, splat_taskq_test1);
557 SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST2_NAME, SPLAT_TASKQ_TEST2_DESC,
558 SPLAT_TASKQ_TEST2_ID, splat_taskq_test2);
e9cb2b4f
BB
559 SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST3_NAME, SPLAT_TASKQ_TEST3_DESC,
560 SPLAT_TASKQ_TEST3_ID, splat_taskq_test3);
7257ec41
BB
561 SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST4_NAME, SPLAT_TASKQ_TEST4_DESC,
562 SPLAT_TASKQ_TEST4_ID, splat_taskq_test4);
5562e5d1
BB
563 SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST5_NAME, SPLAT_TASKQ_TEST5_DESC,
564 SPLAT_TASKQ_TEST5_ID, splat_taskq_test5);
f1ca4da6 565
566 return sub;
567}
568
569void
7c50328b 570splat_taskq_fini(splat_subsystem_t *sub)
f1ca4da6 571{
572 ASSERT(sub);
5562e5d1 573 SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST5_ID);
7257ec41 574 SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST4_ID);
e9cb2b4f 575 SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST3_ID);
7c50328b 576 SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST2_ID);
577 SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST1_ID);
f1ca4da6 578
579 kfree(sub);
580}
581
582int
7c50328b 583splat_taskq_id(void) {
584 return SPLAT_SUBSYSTEM_TASKQ;
f1ca4da6 585}