1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) Task Queue Tests.
25 \*****************************************************************************/
27 #include "splat-internal.h"
29 #define SPLAT_TASKQ_NAME "taskq"
30 #define SPLAT_TASKQ_DESC "Kernel Task Queue Tests"
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"
36 #define SPLAT_TASKQ_TEST2_ID 0x0202
37 #define SPLAT_TASKQ_TEST2_NAME "multiple"
38 #define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
40 #define SPLAT_TASKQ_TEST3_ID 0x0203
41 #define SPLAT_TASKQ_TEST3_NAME "system"
42 #define SPLAT_TASKQ_TEST3_DESC "System task queue, multiple tasks"
44 #define SPLAT_TASKQ_TEST4_ID 0x0204
45 #define SPLAT_TASKQ_TEST4_NAME "wait"
46 #define SPLAT_TASKQ_TEST4_DESC "Multiple task waiting"
48 #define SPLAT_TASKQ_TEST5_ID 0x0205
49 #define SPLAT_TASKQ_TEST5_NAME "order"
50 #define SPLAT_TASKQ_TEST5_DESC "Correct task ordering"
52 #define SPLAT_TASKQ_TEST6_ID 0x0206
53 #define SPLAT_TASKQ_TEST6_NAME "front"
54 #define SPLAT_TASKQ_TEST6_DESC "Correct ordering with TQ_FRONT flag"
56 #define SPLAT_TASKQ_ORDER_MAX 8
58 typedef struct splat_taskq_arg
{
62 int order
[SPLAT_TASKQ_ORDER_MAX
];
68 typedef struct splat_taskq_id
{
70 splat_taskq_arg_t
*arg
;
74 * Create a taskq, queue a task, wait until task completes, ensure
75 * task ran properly, cleanup taskq.
78 splat_taskq_test13_func(void *arg
)
80 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
83 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST1_NAME
,
84 "Taskq '%s' function '%s' setting flag\n",
85 tq_arg
->name
, sym2str(splat_taskq_test13_func
));
90 splat_taskq_test1(struct file
*file
, void *arg
)
94 splat_taskq_arg_t tq_arg
;
96 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' creating\n",
97 SPLAT_TASKQ_TEST1_NAME
);
98 if ((tq
= taskq_create(SPLAT_TASKQ_TEST1_NAME
, 1, maxclsyspri
,
99 50, INT_MAX
, TASKQ_PREPOPULATE
)) == NULL
) {
100 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
101 "Taskq '%s' create failed\n",
102 SPLAT_TASKQ_TEST1_NAME
);
109 tq_arg
.name
= SPLAT_TASKQ_TEST1_NAME
;
111 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
112 "Taskq '%s' function '%s' dispatching\n",
113 tq_arg
.name
, sym2str(splat_taskq_test13_func
));
114 if ((id
= taskq_dispatch(tq
, splat_taskq_test13_func
,
115 &tq_arg
, TQ_SLEEP
)) == 0) {
116 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
117 "Taskq '%s' function '%s' dispatch failed\n",
118 tq_arg
.name
, sym2str(splat_taskq_test13_func
));
123 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' waiting\n",
126 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' destroying\n",
130 return (tq_arg
.flag
) ? 0 : -EINVAL
;
134 * Create multiple taskq's, each with multiple tasks, wait until
135 * all tasks complete, ensure all tasks ran properly and in the
136 * correct order. Run order must be the same as the order submitted
137 * because we only have 1 thread per taskq. Finally cleanup the taskq.
140 splat_taskq_test2_func1(void *arg
)
142 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
145 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
146 "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
147 tq_arg
->name
, tq_arg
->id
,
148 sym2str(splat_taskq_test2_func1
),
149 tq_arg
->flag
* 2, tq_arg
->flag
);
154 splat_taskq_test2_func2(void *arg
)
156 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
159 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
160 "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
161 tq_arg
->name
, tq_arg
->id
,
162 sym2str(splat_taskq_test2_func2
),
163 tq_arg
->flag
+ 1, tq_arg
->flag
);
167 #define TEST2_TASKQS 8
168 #define TEST2_THREADS_PER_TASKQ 1
171 splat_taskq_test2(struct file
*file
, void *arg
) {
172 taskq_t
*tq
[TEST2_TASKQS
] = { NULL
};
174 splat_taskq_arg_t tq_args
[TEST2_TASKQS
];
177 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
179 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
, "Taskq '%s/%d' "
180 "creating\n", SPLAT_TASKQ_TEST2_NAME
, i
);
181 if ((tq
[i
] = taskq_create(SPLAT_TASKQ_TEST2_NAME
,
182 TEST2_THREADS_PER_TASKQ
,
183 maxclsyspri
, 50, INT_MAX
,
184 TASKQ_PREPOPULATE
)) == NULL
) {
185 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
186 "Taskq '%s/%d' create failed\n",
187 SPLAT_TASKQ_TEST2_NAME
, i
);
194 tq_args
[i
].file
= file
;
195 tq_args
[i
].name
= SPLAT_TASKQ_TEST2_NAME
;
197 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
198 "Taskq '%s/%d' function '%s' dispatching\n",
199 tq_args
[i
].name
, tq_args
[i
].id
,
200 sym2str(splat_taskq_test2_func1
));
201 if ((id
= taskq_dispatch(
202 tq
[i
], splat_taskq_test2_func1
,
203 &tq_args
[i
], TQ_SLEEP
)) == 0) {
204 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
205 "Taskq '%s/%d' function '%s' dispatch "
206 "failed\n", tq_args
[i
].name
, tq_args
[i
].id
,
207 sym2str(splat_taskq_test2_func1
));
212 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
213 "Taskq '%s/%d' function '%s' dispatching\n",
214 tq_args
[i
].name
, tq_args
[i
].id
,
215 sym2str(splat_taskq_test2_func2
));
216 if ((id
= taskq_dispatch(
217 tq
[i
], splat_taskq_test2_func2
,
218 &tq_args
[i
], TQ_SLEEP
)) == 0) {
219 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
220 "Taskq '%s/%d' function '%s' dispatch failed\n",
221 tq_args
[i
].name
, tq_args
[i
].id
,
222 sym2str(splat_taskq_test2_func2
));
228 /* When rc is set we're effectively just doing cleanup here, so
229 * ignore new errors in that case. They just cause noise. */
230 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
232 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
233 "Taskq '%s/%d' waiting\n",
234 tq_args
[i
].name
, tq_args
[i
].id
);
236 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
237 "Taskq '%s/%d; destroying\n",
238 tq_args
[i
].name
, tq_args
[i
].id
);
239 taskq_destroy(tq
[i
]);
241 if (!rc
&& tq_args
[i
].flag
!= ((i
* 2) + 1)) {
242 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
243 "Taskq '%s/%d' processed tasks "
244 "out of order; %d != %d\n",
245 tq_args
[i
].name
, tq_args
[i
].id
,
246 tq_args
[i
].flag
, i
* 2 + 1);
249 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
250 "Taskq '%s/%d' processed tasks "
251 "in the correct order; %d == %d\n",
252 tq_args
[i
].name
, tq_args
[i
].id
,
253 tq_args
[i
].flag
, i
* 2 + 1);
262 * Use the global system task queue with a single task, wait until task
263 * completes, ensure task ran properly.
266 splat_taskq_test3(struct file
*file
, void *arg
)
269 splat_taskq_arg_t tq_arg
;
274 tq_arg
.name
= SPLAT_TASKQ_TEST3_NAME
;
276 splat_vprint(file
, SPLAT_TASKQ_TEST3_NAME
,
277 "Taskq '%s' function '%s' dispatching\n",
278 tq_arg
.name
, sym2str(splat_taskq_test13_func
));
279 if ((id
= taskq_dispatch(system_taskq
, splat_taskq_test13_func
,
280 &tq_arg
, TQ_SLEEP
)) == 0) {
281 splat_vprint(file
, SPLAT_TASKQ_TEST3_NAME
,
282 "Taskq '%s' function '%s' dispatch failed\n",
283 tq_arg
.name
, sym2str(splat_taskq_test13_func
));
287 splat_vprint(file
, SPLAT_TASKQ_TEST3_NAME
, "Taskq '%s' waiting\n",
289 taskq_wait(system_taskq
);
291 return (tq_arg
.flag
) ? 0 : -EINVAL
;
295 * Create a taskq and dispatch a large number of tasks to the queue.
296 * Then use taskq_wait() to block until all the tasks complete, then
297 * cross check that all the tasks ran by checking tg_arg->count which
298 * is incremented in the task function. Finally cleanup the taskq.
300 * First we try with a large 'maxalloc' value, then we try with a small one.
301 * We should not drop tasks when TQ_SLEEP is used in taskq_dispatch(), even
302 * if the number of pending tasks is above maxalloc.
305 splat_taskq_test4_func(void *arg
)
307 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
310 atomic_inc(&tq_arg
->count
);
314 splat_taskq_test4_common(struct file
*file
, void *arg
, int minalloc
,
315 int maxalloc
, int nr_tasks
)
318 splat_taskq_arg_t tq_arg
;
321 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
, "Taskq '%s' creating "
322 "(%d/%d/%d)\n", SPLAT_TASKQ_TEST4_NAME
, minalloc
, maxalloc
,
324 if ((tq
= taskq_create(SPLAT_TASKQ_TEST4_NAME
, 1, maxclsyspri
,
325 minalloc
, maxalloc
, TASKQ_PREPOPULATE
)) == NULL
) {
326 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
,
327 "Taskq '%s' create failed\n",
328 SPLAT_TASKQ_TEST4_NAME
);
333 tq_arg
.name
= SPLAT_TASKQ_TEST4_NAME
;
335 for (i
= 1; i
<= nr_tasks
; i
*= 2) {
336 atomic_set(&tq_arg
.count
, 0);
337 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
,
338 "Taskq '%s' function '%s' dispatched %d times\n",
339 tq_arg
.name
, sym2str(splat_taskq_test4_func
), i
);
341 for (j
= 0; j
< i
; j
++) {
342 if ((taskq_dispatch(tq
, splat_taskq_test4_func
,
343 &tq_arg
, TQ_SLEEP
)) == 0) {
344 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
,
345 "Taskq '%s' function '%s' dispatch "
346 "%d failed\n", tq_arg
.name
,
347 sym2str(splat_taskq_test13_func
), j
);
353 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
, "Taskq '%s' "
354 "waiting for %d dispatches\n", tq_arg
.name
, i
);
356 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
, "Taskq '%s' "
357 "%d/%d dispatches finished\n", tq_arg
.name
,
358 atomic_read(&tq_arg
.count
), i
);
359 if (atomic_read(&tq_arg
.count
) != i
) {
366 splat_vprint(file
, SPLAT_TASKQ_TEST4_NAME
, "Taskq '%s' destroying\n",
373 static int splat_taskq_test4(struct file
*file
, void *arg
)
377 rc
= splat_taskq_test4_common(file
, arg
, 50, INT_MAX
, 1024);
381 rc
= splat_taskq_test4_common(file
, arg
, 1, 1, 32);
387 * Create a taskq and dispatch a specific sequence of tasks carefully
388 * crafted to validate the order in which tasks are processed. When
389 * there are multiple worker threads each thread will process the
390 * next pending task as soon as it completes its current task. This
391 * means that tasks do not strictly complete in order in which they
392 * were dispatched (increasing task id). This is fine but we need to
393 * verify that taskq_wait_id() blocks until the passed task id and all
394 * lower task ids complete. We do this by dispatching the following
395 * specific sequence of tasks each of which block for N time units.
396 * We then use taskq_wait_id() to unblock at specific task id and
397 * verify the only the expected task ids have completed and in the
398 * correct order. The two cases of interest are:
400 * 1) Task ids larger than the waited for task id can run and
401 * complete as long as there is an available worker thread.
402 * 2) All task ids lower than the waited one must complete before
403 * unblocking even if the waited task id itself has completed.
405 * The following table shows each task id and how they will be
406 * scheduled. Each rows represent one time unit and each column
407 * one of the three worker threads. The places taskq_wait_id()
408 * must unblock for a specific id are identified as well as the
409 * task ids which must have completed and their order.
411 * +-----+ <--- taskq_wait_id(tq, 8) unblocks
412 * | | Required Completion Order: 1,2,4,5,3,8,6,7
417 * | | +-----+ <--- taskq_wait_id(tq, 3) unblocks
418 * | | 7 | | Required Completion Order: 1,2,4,5,3
427 * +-----+-----+-----+
431 splat_taskq_test5_func(void *arg
)
433 splat_taskq_id_t
*tq_id
= (splat_taskq_id_t
*)arg
;
434 splat_taskq_arg_t
*tq_arg
= tq_id
->arg
;
437 /* Delays determined by above table */
439 default: factor
= 0; break;
440 case 1: case 8: factor
= 1; break;
441 case 2: case 4: case 5: factor
= 2; break;
442 case 6: case 7: factor
= 4; break;
443 case 3: factor
= 5; break;
446 msleep(factor
* 100);
447 splat_vprint(tq_arg
->file
, tq_arg
->name
,
448 "Taskqid %d complete for taskq '%s'\n",
449 tq_id
->id
, tq_arg
->name
);
451 spin_lock(&tq_arg
->lock
);
452 tq_arg
->order
[tq_arg
->flag
] = tq_id
->id
;
454 spin_unlock(&tq_arg
->lock
);
458 splat_taskq_test_order(splat_taskq_arg_t
*tq_arg
, int *order
)
462 for (i
= 0; i
< SPLAT_TASKQ_ORDER_MAX
; i
++) {
463 if (tq_arg
->order
[i
] != order
[i
]) {
464 splat_vprint(tq_arg
->file
, tq_arg
->name
,
465 "Taskq '%s' incorrect completion "
466 "order\n", tq_arg
->name
);
467 splat_vprint(tq_arg
->file
, tq_arg
->name
,
468 "%s", "Expected { ");
470 for (j
= 0; j
< SPLAT_TASKQ_ORDER_MAX
; j
++)
471 splat_print(tq_arg
->file
, "%d ", order
[j
]);
473 splat_print(tq_arg
->file
, "%s", "}\n");
474 splat_vprint(tq_arg
->file
, tq_arg
->name
,
477 for (j
= 0; j
< SPLAT_TASKQ_ORDER_MAX
; j
++)
478 splat_print(tq_arg
->file
, "%d ",
481 splat_print(tq_arg
->file
, "%s", "}\n");
486 splat_vprint(tq_arg
->file
, tq_arg
->name
,
487 "Taskq '%s' validated correct completion order\n",
494 splat_taskq_test5(struct file
*file
, void *arg
)
498 splat_taskq_id_t tq_id
[SPLAT_TASKQ_ORDER_MAX
];
499 splat_taskq_arg_t tq_arg
;
500 int order1
[SPLAT_TASKQ_ORDER_MAX
] = { 1,2,4,5,3,0,0,0 };
501 int order2
[SPLAT_TASKQ_ORDER_MAX
] = { 1,2,4,5,3,8,6,7 };
504 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
, "Taskq '%s' creating\n",
505 SPLAT_TASKQ_TEST5_NAME
);
506 if ((tq
= taskq_create(SPLAT_TASKQ_TEST5_NAME
, 3, maxclsyspri
,
507 50, INT_MAX
, TASKQ_PREPOPULATE
)) == NULL
) {
508 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
,
509 "Taskq '%s' create failed\n",
510 SPLAT_TASKQ_TEST5_NAME
);
515 memset(&tq_arg
.order
, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX
);
516 spin_lock_init(&tq_arg
.lock
);
518 tq_arg
.name
= SPLAT_TASKQ_TEST5_NAME
;
520 for (i
= 0; i
< SPLAT_TASKQ_ORDER_MAX
; i
++) {
522 tq_id
[i
].arg
= &tq_arg
;
524 if ((id
= taskq_dispatch(tq
, splat_taskq_test5_func
,
525 &tq_id
[i
], TQ_SLEEP
)) == 0) {
526 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
,
527 "Taskq '%s' function '%s' dispatch failed\n",
528 tq_arg
.name
, sym2str(splat_taskq_test5_func
));
533 if (tq_id
[i
].id
!= id
) {
534 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
,
535 "Taskq '%s' expected taskqid %d got %d\n",
536 tq_arg
.name
, (int)tq_id
[i
].id
, (int)id
);
542 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
, "Taskq '%s' "
543 "waiting for taskqid %d completion\n", tq_arg
.name
, 3);
544 taskq_wait_id(tq
, 3);
545 if ((rc
= splat_taskq_test_order(&tq_arg
, order1
)))
548 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
, "Taskq '%s' "
549 "waiting for taskqid %d completion\n", tq_arg
.name
, 8);
550 taskq_wait_id(tq
, 8);
551 rc
= splat_taskq_test_order(&tq_arg
, order2
);
554 splat_vprint(file
, SPLAT_TASKQ_TEST5_NAME
,
555 "Taskq '%s' destroying\n", tq_arg
.name
);
562 * Create a single task queue with three threads. Dispatch 8 tasks,
563 * setting TQ_FRONT on only the last three. Sleep after
564 * dispatching tasks 1-3 to ensure they will run and hold the threads
565 * busy while we dispatch the remaining tasks. Verify that tasks 6-8
566 * run before task 4-5.
568 * The following table shows each task id and how they will be
569 * scheduled. Each rows represent one time unit and each column
570 * one of the three worker threads.
588 * +-----+-----+-----+
592 splat_taskq_test6_func(void *arg
)
594 splat_taskq_id_t
*tq_id
= (splat_taskq_id_t
*)arg
;
595 splat_taskq_arg_t
*tq_arg
= tq_id
->arg
;
598 /* Delays determined by above table */
600 default: factor
= 0; break;
601 case 1: factor
= 2; break;
602 case 2: case 4: case 5: factor
= 4; break;
603 case 6: case 7: case 8: factor
= 5; break;
604 case 3: factor
= 6; break;
607 msleep(factor
* 100);
609 splat_vprint(tq_arg
->file
, tq_arg
->name
,
610 "Taskqid %d complete for taskq '%s'\n",
611 tq_id
->id
, tq_arg
->name
);
613 spin_lock(&tq_arg
->lock
);
614 tq_arg
->order
[tq_arg
->flag
] = tq_id
->id
;
616 spin_unlock(&tq_arg
->lock
);
620 splat_taskq_test6(struct file
*file
, void *arg
)
624 splat_taskq_id_t tq_id
[SPLAT_TASKQ_ORDER_MAX
];
625 splat_taskq_arg_t tq_arg
;
626 int order
[SPLAT_TASKQ_ORDER_MAX
] = { 1,2,3,6,7,8,4,5 };
630 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
, "Taskq '%s' creating\n",
631 SPLAT_TASKQ_TEST6_NAME
);
632 if ((tq
= taskq_create(SPLAT_TASKQ_TEST6_NAME
, 3, maxclsyspri
,
633 50, INT_MAX
, TASKQ_PREPOPULATE
)) == NULL
) {
634 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
,
635 "Taskq '%s' create failed\n",
636 SPLAT_TASKQ_TEST6_NAME
);
641 memset(&tq_arg
.order
, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX
);
642 spin_lock_init(&tq_arg
.lock
);
644 tq_arg
.name
= SPLAT_TASKQ_TEST6_NAME
;
646 for (i
= 0; i
< SPLAT_TASKQ_ORDER_MAX
; i
++) {
648 tq_id
[i
].arg
= &tq_arg
;
653 if ((id
= taskq_dispatch(tq
, splat_taskq_test6_func
,
654 &tq_id
[i
], tflags
)) == 0) {
655 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
,
656 "Taskq '%s' function '%s' dispatch failed\n",
657 tq_arg
.name
, sym2str(splat_taskq_test6_func
));
662 if (tq_id
[i
].id
!= id
) {
663 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
,
664 "Taskq '%s' expected taskqid %d got %d\n",
665 tq_arg
.name
, (int)tq_id
[i
].id
, (int)id
);
669 /* Sleep to let tasks 1-3 start executing. */
674 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
, "Taskq '%s' "
675 "waiting for taskqid %d completion\n", tq_arg
.name
,
676 SPLAT_TASKQ_ORDER_MAX
);
677 taskq_wait_id(tq
, SPLAT_TASKQ_ORDER_MAX
);
678 rc
= splat_taskq_test_order(&tq_arg
, order
);
681 splat_vprint(file
, SPLAT_TASKQ_TEST6_NAME
,
682 "Taskq '%s' destroying\n", tq_arg
.name
);
689 splat_taskq_init(void)
691 splat_subsystem_t
*sub
;
693 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
697 memset(sub
, 0, sizeof(*sub
));
698 strncpy(sub
->desc
.name
, SPLAT_TASKQ_NAME
, SPLAT_NAME_SIZE
);
699 strncpy(sub
->desc
.desc
, SPLAT_TASKQ_DESC
, SPLAT_DESC_SIZE
);
700 INIT_LIST_HEAD(&sub
->subsystem_list
);
701 INIT_LIST_HEAD(&sub
->test_list
);
702 spin_lock_init(&sub
->test_lock
);
703 sub
->desc
.id
= SPLAT_SUBSYSTEM_TASKQ
;
705 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST1_NAME
, SPLAT_TASKQ_TEST1_DESC
,
706 SPLAT_TASKQ_TEST1_ID
, splat_taskq_test1
);
707 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST2_NAME
, SPLAT_TASKQ_TEST2_DESC
,
708 SPLAT_TASKQ_TEST2_ID
, splat_taskq_test2
);
709 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST3_NAME
, SPLAT_TASKQ_TEST3_DESC
,
710 SPLAT_TASKQ_TEST3_ID
, splat_taskq_test3
);
711 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST4_NAME
, SPLAT_TASKQ_TEST4_DESC
,
712 SPLAT_TASKQ_TEST4_ID
, splat_taskq_test4
);
713 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST5_NAME
, SPLAT_TASKQ_TEST5_DESC
,
714 SPLAT_TASKQ_TEST5_ID
, splat_taskq_test5
);
715 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST6_NAME
, SPLAT_TASKQ_TEST6_DESC
,
716 SPLAT_TASKQ_TEST6_ID
, splat_taskq_test6
);
722 splat_taskq_fini(splat_subsystem_t
*sub
)
725 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST5_ID
);
726 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST4_ID
);
727 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST3_ID
);
728 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST2_ID
);
729 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST1_ID
);
735 splat_taskq_id(void) {
736 return SPLAT_SUBSYSTEM_TASKQ
;