1 #include "splat-internal.h"
3 #define SPLAT_SUBSYSTEM_TASKQ 0x0200
4 #define SPLAT_TASKQ_NAME "taskq"
5 #define SPLAT_TASKQ_DESC "Kernel Task Queue Tests"
7 #define SPLAT_TASKQ_TEST1_ID 0x0201
8 #define SPLAT_TASKQ_TEST1_NAME "single"
9 #define SPLAT_TASKQ_TEST1_DESC "Single task queue, single task"
11 #define SPLAT_TASKQ_TEST2_ID 0x0202
12 #define SPLAT_TASKQ_TEST2_NAME "multiple"
13 #define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
15 typedef struct splat_taskq_arg
{
22 /* Validation Test 1 - Create a taskq, queue a task, wait until
23 * task completes, ensure task ran properly, cleanup taskq,
26 splat_taskq_test1_func(void *arg
)
28 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
31 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST1_NAME
,
32 "Taskq '%s' function '%s' setting flag\n",
33 tq_arg
->name
, sym2str(splat_taskq_test1_func
));
38 splat_taskq_test1(struct file
*file
, void *arg
)
42 splat_taskq_arg_t tq_arg
;
44 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' creating\n",
45 SPLAT_TASKQ_TEST1_NAME
);
46 if ((tq
= taskq_create(SPLAT_TASKQ_TEST1_NAME
, 1, maxclsyspri
,
47 50, INT_MAX
, TASKQ_PREPOPULATE
)) == NULL
) {
48 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
49 "Taskq '%s' create failed\n",
50 SPLAT_TASKQ_TEST1_NAME
);
57 tq_arg
.name
= SPLAT_TASKQ_TEST1_NAME
;
59 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
60 "Taskq '%s' function '%s' dispatching\n",
61 tq_arg
.name
, sym2str(splat_taskq_test1_func
));
62 if ((id
= taskq_dispatch(tq
, splat_taskq_test1_func
,
63 &tq_arg
, TQ_SLEEP
)) == 0) {
64 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
65 "Taskq '%s' function '%s' dispatch failed\n",
66 tq_arg
.name
, sym2str(splat_taskq_test1_func
));
71 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' waiting\n",
74 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' destroying\n",
78 return (tq_arg
.flag
) ? 0 : -EINVAL
;
81 /* Validation Test 2 - Create multiple taskq's, each with multiple tasks,
82 * wait until all tasks complete, ensure all tasks ran properly and in the
83 * the correct order, cleanup taskq's
86 splat_taskq_test2_func1(void *arg
)
88 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
91 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
92 "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
93 tq_arg
->name
, tq_arg
->id
,
94 sym2str(splat_taskq_test2_func1
),
95 tq_arg
->flag
* 2, tq_arg
->flag
);
100 splat_taskq_test2_func2(void *arg
)
102 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
105 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
106 "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
107 tq_arg
->name
, tq_arg
->id
,
108 sym2str(splat_taskq_test2_func2
),
109 tq_arg
->flag
+ 1, tq_arg
->flag
);
113 #define TEST2_TASKQS 8
114 #define TEST2_THREADS_PER_TASKQ 4
117 splat_taskq_test2(struct file
*file
, void *arg
) {
118 taskq_t
*tq
[TEST2_TASKQS
] = { NULL
};
120 splat_taskq_arg_t tq_args
[TEST2_TASKQS
];
123 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
125 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
, "Taskq '%s/%d' "
126 "creating\n", SPLAT_TASKQ_TEST2_NAME
, i
);
127 if ((tq
[i
] = taskq_create(SPLAT_TASKQ_TEST2_NAME
,
128 TEST2_THREADS_PER_TASKQ
,
129 maxclsyspri
, 50, INT_MAX
,
130 TASKQ_PREPOPULATE
)) == NULL
) {
131 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
132 "Taskq '%s/%d' create failed\n",
133 SPLAT_TASKQ_TEST2_NAME
, i
);
140 tq_args
[i
].file
= file
;
141 tq_args
[i
].name
= SPLAT_TASKQ_TEST2_NAME
;
143 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
144 "Taskq '%s/%d' function '%s' dispatching\n",
145 tq_args
[i
].name
, tq_args
[i
].id
,
146 sym2str(splat_taskq_test2_func1
));
147 if ((id
= taskq_dispatch(
148 tq
[i
], splat_taskq_test2_func1
,
149 &tq_args
[i
], TQ_SLEEP
)) == 0) {
150 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
151 "Taskq '%s/%d' function '%s' dispatch "
152 "failed\n", tq_args
[i
].name
, tq_args
[i
].id
,
153 sym2str(splat_taskq_test2_func1
));
158 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
159 "Taskq '%s/%d' function '%s' dispatching\n",
160 tq_args
[i
].name
, tq_args
[i
].id
,
161 sym2str(splat_taskq_test2_func2
));
162 if ((id
= taskq_dispatch(
163 tq
[i
], splat_taskq_test2_func2
,
164 &tq_args
[i
], TQ_SLEEP
)) == 0) {
165 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
166 "Taskq '%s/%d' function '%s' dispatch failed\n",
167 tq_args
[i
].name
, tq_args
[i
].id
,
168 sym2str(splat_taskq_test2_func2
));
174 /* When rc is set we're effectively just doing cleanup here, so
175 * ignore new errors in that case. They just cause noise. */
176 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
178 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
179 "Taskq '%s/%d' waiting\n",
180 tq_args
[i
].name
, tq_args
[i
].id
);
182 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
183 "Taskq '%s/%d; destroying\n",
184 tq_args
[i
].name
, tq_args
[i
].id
);
185 taskq_destroy(tq
[i
]);
187 if (!rc
&& tq_args
[i
].flag
!= ((i
* 2) + 1)) {
188 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
189 "Taskq '%s/%d' processed tasks "
190 "out of order; %d != %d\n",
191 tq_args
[i
].name
, tq_args
[i
].id
,
192 tq_args
[i
].flag
, i
* 2 + 1);
195 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
196 "Taskq '%s/%d' processed tasks "
197 "in the correct order; %d == %d\n",
198 tq_args
[i
].name
, tq_args
[i
].id
,
199 tq_args
[i
].flag
, i
* 2 + 1);
208 splat_taskq_init(void)
210 splat_subsystem_t
*sub
;
212 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
216 memset(sub
, 0, sizeof(*sub
));
217 strncpy(sub
->desc
.name
, SPLAT_TASKQ_NAME
, SPLAT_NAME_SIZE
);
218 strncpy(sub
->desc
.desc
, SPLAT_TASKQ_DESC
, SPLAT_DESC_SIZE
);
219 INIT_LIST_HEAD(&sub
->subsystem_list
);
220 INIT_LIST_HEAD(&sub
->test_list
);
221 spin_lock_init(&sub
->test_lock
);
222 sub
->desc
.id
= SPLAT_SUBSYSTEM_TASKQ
;
224 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST1_NAME
, SPLAT_TASKQ_TEST1_DESC
,
225 SPLAT_TASKQ_TEST1_ID
, splat_taskq_test1
);
226 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST2_NAME
, SPLAT_TASKQ_TEST2_DESC
,
227 SPLAT_TASKQ_TEST2_ID
, splat_taskq_test2
);
233 splat_taskq_fini(splat_subsystem_t
*sub
)
236 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST2_ID
);
237 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST1_ID
);
243 splat_taskq_id(void) {
244 return SPLAT_SUBSYSTEM_TASKQ
;