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, 0, 0, 0, 0)) == NULL
) {
47 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
48 "Taskq '%s' create failed\n",
49 SPLAT_TASKQ_TEST1_NAME
);
56 tq_arg
.name
= SPLAT_TASKQ_TEST1_NAME
;
58 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
59 "Taskq '%s' function '%s' dispatching\n",
60 tq_arg
.name
, sym2str(splat_taskq_test1_func
));
61 if ((id
= taskq_dispatch(tq
, splat_taskq_test1_func
, &tq_arg
, 0)) == 0) {
62 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
,
63 "Taskq '%s' function '%s' dispatch failed\n",
64 tq_arg
.name
, sym2str(splat_taskq_test1_func
));
69 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' waiting\n",
72 splat_vprint(file
, SPLAT_TASKQ_TEST1_NAME
, "Taskq '%s' destroying\n",
76 return (tq_arg
.flag
) ? 0 : -EINVAL
;
79 /* Validation Test 2 - Create multiple taskq's, each with multiple tasks,
80 * wait until all tasks complete, ensure all tasks ran properly and in the
81 * the correct order, cleanup taskq's
84 splat_taskq_test2_func1(void *arg
)
86 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
89 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
90 "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
91 tq_arg
->name
, tq_arg
->id
,
92 sym2str(splat_taskq_test2_func1
),
93 tq_arg
->flag
* 2, tq_arg
->flag
);
98 splat_taskq_test2_func2(void *arg
)
100 splat_taskq_arg_t
*tq_arg
= (splat_taskq_arg_t
*)arg
;
103 splat_vprint(tq_arg
->file
, SPLAT_TASKQ_TEST2_NAME
,
104 "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
105 tq_arg
->name
, tq_arg
->id
,
106 sym2str(splat_taskq_test2_func2
),
107 tq_arg
->flag
+ 1, tq_arg
->flag
);
111 #define TEST2_TASKQS 8
113 splat_taskq_test2(struct file
*file
, void *arg
) {
114 taskq_t
*tq
[TEST2_TASKQS
] = { NULL
};
116 splat_taskq_arg_t tq_args
[TEST2_TASKQS
];
119 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
121 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
, "Taskq '%s/%d' "
122 "creating\n", SPLAT_TASKQ_TEST2_NAME
, i
);
123 if ((tq
[i
] = taskq_create(SPLAT_TASKQ_TEST2_NAME
,
124 1, 0, 0, 0, 0)) == NULL
) {
125 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
126 "Taskq '%s/%d' create failed\n",
127 SPLAT_TASKQ_TEST2_NAME
, i
);
134 tq_args
[i
].file
= file
;
135 tq_args
[i
].name
= SPLAT_TASKQ_TEST2_NAME
;
137 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
138 "Taskq '%s/%d' function '%s' dispatching\n",
139 tq_args
[i
].name
, tq_args
[i
].id
,
140 sym2str(splat_taskq_test2_func1
));
141 if ((id
= taskq_dispatch(
142 tq
[i
], splat_taskq_test2_func1
, &tq_args
[i
], 0)) == 0) {
143 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
144 "Taskq '%s/%d' function '%s' dispatch "
145 "failed\n", tq_args
[i
].name
, tq_args
[i
].id
,
146 sym2str(splat_taskq_test2_func1
));
151 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
152 "Taskq '%s/%d' function '%s' dispatching\n",
153 tq_args
[i
].name
, tq_args
[i
].id
,
154 sym2str(splat_taskq_test2_func2
));
155 if ((id
= taskq_dispatch(
156 tq
[i
], splat_taskq_test2_func2
, &tq_args
[i
], 0)) == 0) {
157 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
158 "Taskq '%s/%d' function '%s' dispatch failed\n",
159 tq_args
[i
].name
, tq_args
[i
].id
,
160 sym2str(splat_taskq_test2_func2
));
166 /* When rc is set we're effectively just doing cleanup here, so
167 * ignore new errors in that case. They just cause noise. */
168 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
170 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
171 "Taskq '%s/%d' waiting\n",
172 tq_args
[i
].name
, tq_args
[i
].id
);
174 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
175 "Taskq '%s/%d; destroying\n",
176 tq_args
[i
].name
, tq_args
[i
].id
);
177 taskq_destory(tq
[i
]);
179 if (!rc
&& tq_args
[i
].flag
!= ((i
* 2) + 1)) {
180 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
181 "Taskq '%s/%d' processed tasks "
182 "out of order; %d != %d\n",
183 tq_args
[i
].name
, tq_args
[i
].id
,
184 tq_args
[i
].flag
, i
* 2 + 1);
187 splat_vprint(file
, SPLAT_TASKQ_TEST2_NAME
,
188 "Taskq '%s/%d' processed tasks "
189 "in the correct order; %d == %d\n",
190 tq_args
[i
].name
, tq_args
[i
].id
,
191 tq_args
[i
].flag
, i
* 2 + 1);
200 splat_taskq_init(void)
202 splat_subsystem_t
*sub
;
204 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
208 memset(sub
, 0, sizeof(*sub
));
209 strncpy(sub
->desc
.name
, SPLAT_TASKQ_NAME
, SPLAT_NAME_SIZE
);
210 strncpy(sub
->desc
.desc
, SPLAT_TASKQ_DESC
, SPLAT_DESC_SIZE
);
211 INIT_LIST_HEAD(&sub
->subsystem_list
);
212 INIT_LIST_HEAD(&sub
->test_list
);
213 spin_lock_init(&sub
->test_lock
);
214 sub
->desc
.id
= SPLAT_SUBSYSTEM_TASKQ
;
216 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST1_NAME
, SPLAT_TASKQ_TEST1_DESC
,
217 SPLAT_TASKQ_TEST1_ID
, splat_taskq_test1
);
218 SPLAT_TEST_INIT(sub
, SPLAT_TASKQ_TEST2_NAME
, SPLAT_TASKQ_TEST2_DESC
,
219 SPLAT_TASKQ_TEST2_ID
, splat_taskq_test2
);
225 splat_taskq_fini(splat_subsystem_t
*sub
)
228 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST2_ID
);
229 SPLAT_TEST_FINI(sub
, SPLAT_TASKQ_TEST1_ID
);
235 splat_taskq_id(void) {
236 return SPLAT_SUBSYSTEM_TASKQ
;