Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk_internal/cunit.h"
10 : :
11 : : #include "thread/thread_internal.h"
12 : :
13 : : #include "thread/thread.c"
14 : : #include "common/lib/ut_multithread.c"
15 : :
16 : : static int g_sched_rc = 0;
17 : :
18 : : static int
19 : 20 : _thread_schedule(struct spdk_thread *thread)
20 : : {
21 : 20 : return g_sched_rc;
22 : : }
23 : :
24 : : static bool
25 : 10 : _thread_op_supported(enum spdk_thread_op op)
26 : : {
27 [ + - ]: 10 : switch (op) {
28 : 10 : case SPDK_THREAD_OP_NEW:
29 : 10 : return true;
30 : 0 : default:
31 : 0 : return false;
32 : : }
33 : : }
34 : :
35 : : static int
36 : 10 : _thread_op(struct spdk_thread *thread, enum spdk_thread_op op)
37 : : {
38 [ + - ]: 10 : switch (op) {
39 : 10 : case SPDK_THREAD_OP_NEW:
40 : 10 : return _thread_schedule(thread);
41 : 0 : default:
42 : 0 : return -ENOTSUP;
43 : : }
44 : : }
45 : :
46 : : static void
47 : 5 : thread_alloc(void)
48 : : {
49 : : struct spdk_thread *thread;
50 : :
51 : : /* No schedule callback */
52 : 5 : spdk_thread_lib_init(NULL, 0);
53 : 5 : thread = spdk_thread_create(NULL, NULL);
54 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
55 : 5 : spdk_set_thread(thread);
56 : 5 : spdk_thread_exit(thread);
57 [ + + ]: 10 : while (!spdk_thread_is_exited(thread)) {
58 : 5 : spdk_thread_poll(thread, 0, 0);
59 : : }
60 : 5 : spdk_thread_destroy(thread);
61 : 5 : spdk_thread_lib_fini();
62 : :
63 : : /* Schedule callback exists */
64 : 5 : spdk_thread_lib_init(_thread_schedule, 0);
65 : :
66 : : /* Scheduling succeeds */
67 : 5 : g_sched_rc = 0;
68 : 5 : thread = spdk_thread_create(NULL, NULL);
69 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
70 : 5 : spdk_set_thread(thread);
71 : 5 : spdk_thread_exit(thread);
72 [ + + ]: 10 : while (!spdk_thread_is_exited(thread)) {
73 : 5 : spdk_thread_poll(thread, 0, 0);
74 : : }
75 : 5 : spdk_thread_destroy(thread);
76 : :
77 : : /* Scheduling fails */
78 : 5 : g_sched_rc = -1;
79 : 5 : thread = spdk_thread_create(NULL, NULL);
80 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread == NULL);
81 : :
82 : 5 : spdk_thread_lib_fini();
83 : :
84 : : /* Scheduling callback exists with extended thread library initialization. */
85 : 5 : spdk_thread_lib_init_ext(_thread_op, _thread_op_supported, 0,
86 : : SPDK_DEFAULT_MSG_MEMPOOL_SIZE);
87 : :
88 : : /* Scheduling succeeds */
89 : 5 : g_sched_rc = 0;
90 : 5 : thread = spdk_thread_create(NULL, NULL);
91 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
92 : 5 : spdk_set_thread(thread);
93 : 5 : spdk_thread_exit(thread);
94 [ + + ]: 10 : while (!spdk_thread_is_exited(thread)) {
95 : 5 : spdk_thread_poll(thread, 0, 0);
96 : : }
97 : 5 : spdk_thread_destroy(thread);
98 : :
99 : : /* Scheduling fails */
100 : 5 : g_sched_rc = -1;
101 : 5 : thread = spdk_thread_create(NULL, NULL);
102 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread == NULL);
103 : :
104 : 5 : spdk_thread_lib_fini();
105 : 5 : }
106 : :
107 : : static void
108 : 15 : send_msg_cb(void *ctx)
109 : : {
110 : 15 : bool *done = ctx;
111 : :
112 : 15 : *done = true;
113 : 15 : }
114 : :
115 : : static void
116 : 5 : thread_send_msg(void)
117 : : {
118 : : struct spdk_thread *thread0;
119 : 5 : bool done = false;
120 : :
121 : 5 : allocate_threads(2);
122 : 5 : set_thread(0);
123 : 5 : thread0 = spdk_get_thread();
124 : :
125 : 5 : set_thread(1);
126 : : /* Simulate thread 1 sending a message to thread 0. */
127 : 5 : spdk_thread_send_msg(thread0, send_msg_cb, &done);
128 : :
129 : : /* We have not polled thread 0 yet, so done should be false. */
130 [ - + ]: 5 : CU_ASSERT(!done);
131 : :
132 : : /*
133 : : * Poll thread 1. The message was sent to thread 0, so this should be
134 : : * a nop and done should still be false.
135 : : */
136 : 5 : poll_thread(1);
137 [ - + ]: 5 : CU_ASSERT(!done);
138 : :
139 : : /*
140 : : * Poll thread 0. This should execute the message and done should then
141 : : * be true.
142 : : */
143 : 5 : poll_thread(0);
144 [ - + ]: 5 : CU_ASSERT(done);
145 : :
146 : 5 : free_threads();
147 : 5 : }
148 : :
149 : : static int
150 : 90 : poller_run_done(void *ctx)
151 : : {
152 : 90 : bool *poller_run = ctx;
153 : :
154 : 90 : *poller_run = true;
155 : :
156 : 90 : return -1;
157 : : }
158 : :
159 : : static void
160 : 5 : thread_poller(void)
161 : : {
162 : 5 : struct spdk_poller *poller = NULL;
163 : 5 : bool poller_run = false;
164 : :
165 : 5 : allocate_threads(1);
166 : :
167 : 5 : set_thread(0);
168 : 5 : MOCK_SET(spdk_get_ticks, 0);
169 : : /* Register a poller with no-wait time and test execution */
170 : 5 : poller = spdk_poller_register(poller_run_done, &poller_run, 0);
171 : 5 : CU_ASSERT(poller != NULL);
172 : :
173 : 5 : poll_threads();
174 [ - + ]: 5 : CU_ASSERT(poller_run == true);
175 : :
176 : 5 : spdk_poller_unregister(&poller);
177 : 5 : CU_ASSERT(poller == NULL);
178 : :
179 : : /* Register a poller with 1000us wait time and test single execution */
180 : 5 : poller_run = false;
181 : 5 : poller = spdk_poller_register(poller_run_done, &poller_run, 1000);
182 : 5 : CU_ASSERT(poller != NULL);
183 : :
184 : 5 : poll_threads();
185 [ - + ]: 5 : CU_ASSERT(poller_run == false);
186 : :
187 : 5 : spdk_delay_us(1000);
188 : 5 : poll_threads();
189 [ - + ]: 5 : CU_ASSERT(poller_run == true);
190 : :
191 : 5 : poller_run = false;
192 : 5 : poll_threads();
193 [ - + ]: 5 : CU_ASSERT(poller_run == false);
194 : :
195 : 5 : spdk_delay_us(1000);
196 : 5 : poll_threads();
197 [ - + ]: 5 : CU_ASSERT(poller_run == true);
198 : :
199 : 5 : spdk_poller_unregister(&poller);
200 : 5 : CU_ASSERT(poller == NULL);
201 : :
202 : 5 : free_threads();
203 : 5 : }
204 : :
205 : : struct poller_ctx {
206 : : struct spdk_poller *poller;
207 : : bool run;
208 : : };
209 : :
210 : : static int
211 : 25 : poller_run_pause(void *ctx)
212 : : {
213 : 25 : struct poller_ctx *poller_ctx = ctx;
214 : :
215 : 25 : poller_ctx->run = true;
216 : 25 : spdk_poller_pause(poller_ctx->poller);
217 : :
218 : 25 : return 0;
219 : : }
220 : :
221 : : /* Verify the same poller can be switched multiple times between
222 : : * pause and resume while it runs.
223 : : */
224 : : static int
225 : 25 : poller_run_pause_resume_pause(void *ctx)
226 : : {
227 : 25 : struct poller_ctx *poller_ctx = ctx;
228 : :
229 : 25 : poller_ctx->run = true;
230 : :
231 : 25 : spdk_poller_pause(poller_ctx->poller);
232 : 25 : spdk_poller_resume(poller_ctx->poller);
233 : 25 : spdk_poller_pause(poller_ctx->poller);
234 : :
235 : 25 : return 0;
236 : : }
237 : :
238 : : static void
239 : 10 : poller_msg_pause_cb(void *ctx)
240 : : {
241 : 10 : struct spdk_poller *poller = ctx;
242 : :
243 : 10 : spdk_poller_pause(poller);
244 : 10 : }
245 : :
246 : : static void
247 : 10 : poller_msg_resume_cb(void *ctx)
248 : : {
249 : 10 : struct spdk_poller *poller = ctx;
250 : :
251 : 10 : spdk_poller_resume(poller);
252 : 10 : }
253 : :
254 : : static void
255 : 5 : poller_pause(void)
256 : : {
257 : 5 : struct poller_ctx poller_ctx = {};
258 : 5 : unsigned int delay[] = { 0, 1000 };
259 : : unsigned int i;
260 : :
261 : 5 : allocate_threads(1);
262 : 5 : set_thread(0);
263 : :
264 : : /* Register a poller that pauses itself */
265 : 5 : poller_ctx.poller = spdk_poller_register(poller_run_pause, &poller_ctx, 0);
266 : 5 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
267 : :
268 : 5 : poller_ctx.run = false;
269 : 5 : poll_threads();
270 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
271 : :
272 : 5 : poller_ctx.run = false;
273 : 5 : poll_threads();
274 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
275 : :
276 : 5 : spdk_poller_unregister(&poller_ctx.poller);
277 : 5 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
278 : :
279 : : /* Register a poller that switches between pause and resume itself */
280 : 5 : poller_ctx.poller = spdk_poller_register(poller_run_pause_resume_pause, &poller_ctx, 0);
281 : 5 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
282 : :
283 : 5 : poller_ctx.run = false;
284 : 5 : poll_threads();
285 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
286 : :
287 : 5 : poller_ctx.run = false;
288 : 5 : poll_threads();
289 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
290 : :
291 : 5 : spdk_poller_unregister(&poller_ctx.poller);
292 : 5 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
293 : :
294 : : /* Verify that resuming an unpaused poller doesn't do anything */
295 : 5 : poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, 0);
296 : 5 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
297 : :
298 : 5 : spdk_poller_resume(poller_ctx.poller);
299 : :
300 : 5 : poller_ctx.run = false;
301 : 5 : poll_threads();
302 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
303 : :
304 : : /* Verify that pausing the same poller twice works too */
305 : 5 : spdk_poller_pause(poller_ctx.poller);
306 : :
307 : 5 : poller_ctx.run = false;
308 : 5 : poll_threads();
309 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
310 : :
311 : 5 : spdk_poller_pause(poller_ctx.poller);
312 : 5 : poll_threads();
313 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
314 : :
315 : 5 : spdk_poller_resume(poller_ctx.poller);
316 : 5 : poll_threads();
317 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
318 : :
319 : : /* Verify that a poller is run when it's resumed immediately after pausing */
320 : 5 : poller_ctx.run = false;
321 : 5 : spdk_poller_pause(poller_ctx.poller);
322 : 5 : spdk_poller_resume(poller_ctx.poller);
323 : 5 : poll_threads();
324 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
325 : :
326 : 5 : spdk_poller_unregister(&poller_ctx.poller);
327 : 5 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
328 : :
329 : : /* Poll the thread to make sure the previous poller gets unregistered */
330 : 5 : poll_threads();
331 : 5 : CU_ASSERT_EQUAL(spdk_thread_has_pollers(spdk_get_thread()), false);
332 : :
333 : : /* Verify that it's possible to unregister a paused poller */
334 : 5 : poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, 0);
335 : 5 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
336 : :
337 : 5 : poller_ctx.run = false;
338 : 5 : poll_threads();
339 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, true);
340 : :
341 : 5 : spdk_poller_pause(poller_ctx.poller);
342 : :
343 : 5 : poller_ctx.run = false;
344 : 5 : poll_threads();
345 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
346 : :
347 : 5 : spdk_poller_unregister(&poller_ctx.poller);
348 : :
349 : 5 : poll_threads();
350 [ - + ]: 5 : CU_ASSERT_EQUAL(poller_ctx.run, false);
351 : 5 : CU_ASSERT_EQUAL(spdk_thread_has_pollers(spdk_get_thread()), false);
352 : :
353 : : /* Register pollers with 0 and 1000us wait time and pause/resume them */
354 [ + + ]: 15 : for (i = 0; i < SPDK_COUNTOF(delay); ++i) {
355 : 10 : poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, delay[i]);
356 : 10 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
357 : :
358 : 10 : spdk_delay_us(delay[i]);
359 : 10 : poller_ctx.run = false;
360 : 10 : poll_threads();
361 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
362 : :
363 : 10 : spdk_poller_pause(poller_ctx.poller);
364 : :
365 : 10 : spdk_delay_us(delay[i]);
366 : 10 : poller_ctx.run = false;
367 : 10 : poll_threads();
368 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
369 : :
370 : 10 : spdk_poller_resume(poller_ctx.poller);
371 : :
372 : 10 : spdk_delay_us(delay[i]);
373 : 10 : poll_threads();
374 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
375 : :
376 : : /* Verify that the poller can be paused/resumed from spdk_thread_send_msg */
377 : 10 : spdk_thread_send_msg(spdk_get_thread(), poller_msg_pause_cb, poller_ctx.poller);
378 : :
379 : 10 : spdk_delay_us(delay[i]);
380 : 10 : poller_ctx.run = false;
381 : 10 : poll_threads();
382 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
383 : :
384 : 10 : spdk_thread_send_msg(spdk_get_thread(), poller_msg_resume_cb, poller_ctx.poller);
385 : :
386 : 10 : poll_threads();
387 [ + + ]: 10 : if (delay[i] > 0) {
388 : 5 : spdk_delay_us(delay[i]);
389 : 5 : poll_threads();
390 : : }
391 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
392 : :
393 : 10 : spdk_poller_unregister(&poller_ctx.poller);
394 : 10 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
395 : :
396 : : /* Register a timed poller that pauses itself */
397 : 10 : poller_ctx.poller = spdk_poller_register(poller_run_pause, &poller_ctx, delay[i]);
398 : 10 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
399 : :
400 : 10 : spdk_delay_us(delay[i]);
401 : 10 : poller_ctx.run = false;
402 : 10 : poll_threads();
403 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
404 : :
405 : 10 : poller_ctx.run = false;
406 : 10 : spdk_delay_us(delay[i]);
407 : 10 : poll_threads();
408 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
409 : :
410 : 10 : spdk_poller_resume(poller_ctx.poller);
411 : :
412 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
413 : 10 : spdk_delay_us(delay[i]);
414 : 10 : poll_threads();
415 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
416 : :
417 : 10 : spdk_poller_unregister(&poller_ctx.poller);
418 : 10 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
419 : :
420 : : /* Register a timed poller that switches between pause and resume itself */
421 : 20 : poller_ctx.poller = spdk_poller_register(poller_run_pause_resume_pause,
422 : 10 : &poller_ctx, delay[i]);
423 : 10 : CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
424 : :
425 : 10 : spdk_delay_us(delay[i]);
426 : 10 : poller_ctx.run = false;
427 : 10 : poll_threads();
428 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
429 : :
430 : 10 : poller_ctx.run = false;
431 : 10 : spdk_delay_us(delay[i]);
432 : 10 : poll_threads();
433 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
434 : :
435 : 10 : spdk_poller_resume(poller_ctx.poller);
436 : :
437 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, false);
438 : 10 : spdk_delay_us(delay[i]);
439 : 10 : poll_threads();
440 [ - + ]: 10 : CU_ASSERT_EQUAL(poller_ctx.run, true);
441 : :
442 : 10 : spdk_poller_unregister(&poller_ctx.poller);
443 : 10 : CU_ASSERT_PTR_NULL(poller_ctx.poller);
444 : : }
445 : :
446 : 5 : free_threads();
447 : 5 : }
448 : :
449 : : static void
450 : 40 : for_each_cb(void *ctx)
451 : : {
452 : 40 : int *count = ctx;
453 : :
454 : 40 : (*count)++;
455 : 40 : }
456 : :
457 : : static void
458 : 5 : thread_for_each(void)
459 : : {
460 : 5 : int count = 0;
461 : : int i;
462 : :
463 : 5 : allocate_threads(3);
464 : 5 : set_thread(0);
465 : :
466 : 5 : spdk_for_each_thread(for_each_cb, &count, for_each_cb);
467 : :
468 : : /* We have not polled thread 0 yet, so count should be 0 */
469 : 5 : CU_ASSERT(count == 0);
470 : :
471 : : /* Poll each thread to verify the message is passed to each */
472 [ + + ]: 20 : for (i = 0; i < 3; i++) {
473 : 15 : poll_thread(i);
474 : 15 : CU_ASSERT(count == (i + 1));
475 : : }
476 : :
477 : : /*
478 : : * After each thread is called, the completion calls it
479 : : * one more time.
480 : : */
481 : 5 : poll_thread(0);
482 : 5 : CU_ASSERT(count == 4);
483 : :
484 : 5 : free_threads();
485 : 5 : }
486 : :
487 : : static int
488 : 35 : channel_create(void *io_device, void *ctx_buf)
489 : : {
490 : 35 : int *ch_count = io_device;
491 : :
492 : 35 : (*ch_count)++;
493 : 35 : return 0;
494 : : }
495 : :
496 : : static void
497 : 35 : channel_destroy(void *io_device, void *ctx_buf)
498 : : {
499 : 35 : int *ch_count = io_device;
500 : :
501 : 35 : (*ch_count)--;
502 : 35 : }
503 : :
504 : : static void
505 : 35 : channel_msg(struct spdk_io_channel_iter *i)
506 : : {
507 : 35 : int *msg_count = spdk_io_channel_iter_get_ctx(i);
508 : :
509 : 35 : (*msg_count)++;
510 : 35 : spdk_for_each_channel_continue(i, 0);
511 : 35 : }
512 : :
513 : : static void
514 : 15 : channel_cpl(struct spdk_io_channel_iter *i, int status)
515 : : {
516 : 15 : int *msg_count = spdk_io_channel_iter_get_ctx(i);
517 : :
518 : 15 : (*msg_count)++;
519 : 15 : }
520 : :
521 : : static void
522 : 5 : for_each_channel_remove(void)
523 : : {
524 : : struct spdk_io_channel *ch0, *ch1, *ch2;
525 : 5 : int ch_count = 0;
526 : 5 : int msg_count = 0;
527 : :
528 : 5 : allocate_threads(3);
529 : 5 : set_thread(0);
530 : 5 : spdk_io_device_register(&ch_count, channel_create, channel_destroy, sizeof(int), NULL);
531 : 5 : ch0 = spdk_get_io_channel(&ch_count);
532 : 5 : set_thread(1);
533 : 5 : ch1 = spdk_get_io_channel(&ch_count);
534 : 5 : set_thread(2);
535 : 5 : ch2 = spdk_get_io_channel(&ch_count);
536 : 5 : CU_ASSERT(ch_count == 3);
537 : :
538 : : /*
539 : : * Test that io_channel handles the case where we start to iterate through
540 : : * the channels, and during the iteration, one of the channels is deleted.
541 : : * This is done in some different and sometimes non-intuitive orders, because
542 : : * some operations are deferred and won't execute until their threads are
543 : : * polled.
544 : : *
545 : : * Case #1: Put the I/O channel before spdk_for_each_channel.
546 : : */
547 : 5 : set_thread(0);
548 : 5 : spdk_put_io_channel(ch0);
549 : 5 : CU_ASSERT(ch_count == 3);
550 : 5 : poll_threads();
551 : 5 : CU_ASSERT(ch_count == 2);
552 : 5 : spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
553 : 5 : CU_ASSERT(msg_count == 0);
554 : 5 : poll_threads();
555 : 5 : CU_ASSERT(msg_count == 3);
556 : :
557 : 5 : msg_count = 0;
558 : :
559 : : /*
560 : : * Case #2: Put the I/O channel after spdk_for_each_channel, but before
561 : : * thread 0 is polled.
562 : : */
563 : 5 : ch0 = spdk_get_io_channel(&ch_count);
564 : 5 : CU_ASSERT(ch_count == 3);
565 : 5 : spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
566 : 5 : spdk_put_io_channel(ch0);
567 : 5 : CU_ASSERT(ch_count == 3);
568 : :
569 : 5 : poll_threads();
570 : 5 : CU_ASSERT(ch_count == 2);
571 : 5 : CU_ASSERT(msg_count == 4);
572 : 5 : set_thread(1);
573 : 5 : spdk_put_io_channel(ch1);
574 : 5 : CU_ASSERT(ch_count == 2);
575 : 5 : set_thread(2);
576 : 5 : spdk_put_io_channel(ch2);
577 : 5 : CU_ASSERT(ch_count == 2);
578 : 5 : poll_threads();
579 : 5 : CU_ASSERT(ch_count == 0);
580 : :
581 : 5 : spdk_io_device_unregister(&ch_count, NULL);
582 : 5 : poll_threads();
583 : :
584 : 5 : free_threads();
585 : 5 : }
586 : :
587 : : struct unreg_ctx {
588 : : bool ch_done;
589 : : bool foreach_done;
590 : : };
591 : :
592 : : static void
593 : 5 : unreg_ch_done(struct spdk_io_channel_iter *i)
594 : : {
595 : 5 : struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
596 : :
597 : 5 : ctx->ch_done = true;
598 : :
599 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(i->cur_thread != NULL);
600 : 5 : spdk_for_each_channel_continue(i, 0);
601 : 5 : }
602 : :
603 : : static void
604 : 5 : unreg_foreach_done(struct spdk_io_channel_iter *i, int status)
605 : : {
606 : 5 : struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
607 : :
608 : 5 : ctx->foreach_done = true;
609 : 5 : }
610 : :
611 : : static void
612 : 5 : for_each_channel_unreg(void)
613 : : {
614 : : struct spdk_io_channel *ch0;
615 : : struct io_device *dev;
616 : 5 : struct unreg_ctx ctx = {};
617 : 5 : int io_target = 0;
618 : :
619 : 5 : allocate_threads(1);
620 : 5 : set_thread(0);
621 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
622 : 5 : spdk_io_device_register(&io_target, channel_create, channel_destroy, sizeof(int), NULL);
623 : 5 : CU_ASSERT(!RB_EMPTY(&g_io_devices));
624 : 5 : dev = RB_MIN(io_device_tree, &g_io_devices);
625 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
626 : 5 : CU_ASSERT(RB_NEXT(io_device_tree, &g_io_devices, dev) == NULL);
627 : 5 : ch0 = spdk_get_io_channel(&io_target);
628 : :
629 : 5 : spdk_io_device_register(&io_target, channel_create, channel_destroy, sizeof(int), NULL);
630 : :
631 : : /*
632 : : * There is already a device registered at &io_target, so a new io_device should not
633 : : * have been added to g_io_devices.
634 : : */
635 : 5 : CU_ASSERT(dev == RB_MIN(io_device_tree, &g_io_devices));
636 : 5 : CU_ASSERT(RB_NEXT(io_device_tree, &g_io_devices, dev) == NULL);
637 : :
638 : 5 : spdk_for_each_channel(&io_target, unreg_ch_done, &ctx, unreg_foreach_done);
639 : 5 : spdk_io_device_unregister(&io_target, NULL);
640 : : /*
641 : : * There is an outstanding foreach call on the io_device, so the unregister should not
642 : : * have immediately removed the device.
643 : : */
644 : 5 : CU_ASSERT(dev == RB_MIN(io_device_tree, &g_io_devices));
645 : :
646 : 5 : poll_thread(0);
647 [ - + ]: 5 : CU_ASSERT(ctx.ch_done == true);
648 [ - + ]: 5 : CU_ASSERT(ctx.foreach_done == true);
649 : :
650 : : /*
651 : : * There are no more foreach operations outstanding, so the device should be
652 : : * unregistered.
653 : : */
654 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
655 : :
656 : 5 : set_thread(0);
657 : 5 : spdk_put_io_channel(ch0);
658 : :
659 : 5 : poll_threads();
660 : :
661 : 5 : free_threads();
662 : 5 : }
663 : :
664 : : static void
665 : 5 : thread_name(void)
666 : : {
667 : : struct spdk_thread *thread;
668 : : const char *name;
669 : :
670 : 5 : spdk_thread_lib_init(NULL, 0);
671 : :
672 : : /* Create thread with no name, which automatically generates one */
673 : 5 : thread = spdk_thread_create(NULL, NULL);
674 : 5 : spdk_set_thread(thread);
675 : 5 : thread = spdk_get_thread();
676 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
677 : 5 : name = spdk_thread_get_name(thread);
678 : 5 : CU_ASSERT(name != NULL);
679 : 5 : spdk_thread_exit(thread);
680 [ + + ]: 10 : while (!spdk_thread_is_exited(thread)) {
681 : 5 : spdk_thread_poll(thread, 0, 0);
682 : : }
683 : 5 : spdk_thread_destroy(thread);
684 : :
685 : : /* Create thread named "test_thread" */
686 : 5 : thread = spdk_thread_create("test_thread", NULL);
687 : 5 : spdk_set_thread(thread);
688 : 5 : thread = spdk_get_thread();
689 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
690 : 5 : name = spdk_thread_get_name(thread);
691 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(name != NULL);
692 [ - + ]: 5 : CU_ASSERT(strcmp(name, "test_thread") == 0);
693 : 5 : spdk_thread_exit(thread);
694 [ + + ]: 10 : while (!spdk_thread_is_exited(thread)) {
695 : 5 : spdk_thread_poll(thread, 0, 0);
696 : : }
697 : 5 : spdk_thread_destroy(thread);
698 : :
699 : 5 : spdk_thread_lib_fini();
700 : 5 : }
701 : :
702 : : static uint64_t g_device1;
703 : : static uint64_t g_device2;
704 : : static uint64_t g_device3;
705 : :
706 : : static uint64_t g_ctx1 = 0x1111;
707 : : static uint64_t g_ctx2 = 0x2222;
708 : :
709 : : static int g_create_cb_calls = 0;
710 : : static int g_destroy_cb_calls = 0;
711 : :
712 : : static int
713 : 10 : create_cb_1(void *io_device, void *ctx_buf)
714 : : {
715 : 10 : CU_ASSERT(io_device == &g_device1);
716 : 10 : *(uint64_t *)ctx_buf = g_ctx1;
717 : 10 : g_create_cb_calls++;
718 : 10 : return 0;
719 : : }
720 : :
721 : : static void
722 : 10 : destroy_cb_1(void *io_device, void *ctx_buf)
723 : : {
724 : 10 : CU_ASSERT(io_device == &g_device1);
725 : 10 : CU_ASSERT(*(uint64_t *)ctx_buf == g_ctx1);
726 : 10 : g_destroy_cb_calls++;
727 : 10 : }
728 : :
729 : : static int
730 : 5 : create_cb_2(void *io_device, void *ctx_buf)
731 : : {
732 : 5 : CU_ASSERT(io_device == &g_device2);
733 : 5 : *(uint64_t *)ctx_buf = g_ctx2;
734 : 5 : g_create_cb_calls++;
735 : 5 : return 0;
736 : : }
737 : :
738 : : static void
739 : 5 : destroy_cb_2(void *io_device, void *ctx_buf)
740 : : {
741 : 5 : CU_ASSERT(io_device == &g_device2);
742 : 5 : CU_ASSERT(*(uint64_t *)ctx_buf == g_ctx2);
743 : 5 : g_destroy_cb_calls++;
744 : 5 : }
745 : :
746 : : static void
747 : 5 : channel(void)
748 : : {
749 : : struct spdk_io_channel *ch1, *ch2;
750 : : void *ctx;
751 : :
752 : 5 : allocate_threads(1);
753 : 5 : set_thread(0);
754 : :
755 : 5 : spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);
756 : 5 : spdk_io_device_register(&g_device2, create_cb_2, destroy_cb_2, sizeof(g_ctx2), NULL);
757 : :
758 : 5 : g_create_cb_calls = 0;
759 : 5 : ch1 = spdk_get_io_channel(&g_device1);
760 : 5 : CU_ASSERT(g_create_cb_calls == 1);
761 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
762 : 5 : CU_ASSERT(spdk_io_channel_get_io_device(ch1) == &g_device1);
763 : :
764 : 5 : g_create_cb_calls = 0;
765 : 5 : ch2 = spdk_get_io_channel(&g_device1);
766 : 5 : CU_ASSERT(g_create_cb_calls == 0);
767 : 5 : CU_ASSERT(ch1 == ch2);
768 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
769 : 5 : CU_ASSERT(spdk_io_channel_get_io_device(ch2) == &g_device1);
770 : :
771 : 5 : g_destroy_cb_calls = 0;
772 : 5 : spdk_put_io_channel(ch2);
773 : 5 : poll_threads();
774 : 5 : CU_ASSERT(g_destroy_cb_calls == 0);
775 : :
776 : 5 : g_create_cb_calls = 0;
777 : 5 : ch2 = spdk_get_io_channel(&g_device2);
778 : 5 : CU_ASSERT(g_create_cb_calls == 1);
779 : 5 : CU_ASSERT(ch1 != ch2);
780 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
781 : 5 : CU_ASSERT(spdk_io_channel_get_io_device(ch2) == &g_device2);
782 : :
783 : 5 : ctx = spdk_io_channel_get_ctx(ch2);
784 : 5 : CU_ASSERT(*(uint64_t *)ctx == g_ctx2);
785 : :
786 : 5 : g_destroy_cb_calls = 0;
787 : 5 : spdk_put_io_channel(ch1);
788 : 5 : poll_threads();
789 : 5 : CU_ASSERT(g_destroy_cb_calls == 1);
790 : :
791 : 5 : g_destroy_cb_calls = 0;
792 : 5 : spdk_put_io_channel(ch2);
793 : 5 : poll_threads();
794 : 5 : CU_ASSERT(g_destroy_cb_calls == 1);
795 : :
796 : 5 : ch1 = spdk_get_io_channel(&g_device3);
797 : 5 : CU_ASSERT(ch1 == NULL);
798 : :
799 : 5 : spdk_io_device_unregister(&g_device1, NULL);
800 : 5 : poll_threads();
801 : 5 : spdk_io_device_unregister(&g_device2, NULL);
802 : 5 : poll_threads();
803 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
804 : 5 : free_threads();
805 : 5 : CU_ASSERT(TAILQ_EMPTY(&g_threads));
806 : 5 : }
807 : :
808 : : static int
809 : 5 : create_cb(void *io_device, void *ctx_buf)
810 : : {
811 : 5 : uint64_t *refcnt = (uint64_t *)ctx_buf;
812 : :
813 : 5 : CU_ASSERT(*refcnt == 0);
814 : 5 : *refcnt = 1;
815 : :
816 : 5 : return 0;
817 : : }
818 : :
819 : : static void
820 : 5 : destroy_cb(void *io_device, void *ctx_buf)
821 : : {
822 : 5 : uint64_t *refcnt = (uint64_t *)ctx_buf;
823 : :
824 : 5 : CU_ASSERT(*refcnt == 1);
825 : 5 : *refcnt = 0;
826 : 5 : }
827 : :
828 : : /**
829 : : * This test is checking that a sequence of get, put, get, put without allowing
830 : : * the deferred put operation to complete doesn't result in releasing the memory
831 : : * for the channel twice.
832 : : */
833 : : static void
834 : 5 : channel_destroy_races(void)
835 : : {
836 : 4 : uint64_t device;
837 : : struct spdk_io_channel *ch;
838 : :
839 : 5 : allocate_threads(1);
840 : 5 : set_thread(0);
841 : :
842 : 5 : spdk_io_device_register(&device, create_cb, destroy_cb, sizeof(uint64_t), NULL);
843 : :
844 : 5 : ch = spdk_get_io_channel(&device);
845 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
846 : :
847 : 5 : spdk_put_io_channel(ch);
848 : :
849 : 5 : ch = spdk_get_io_channel(&device);
850 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
851 : :
852 : 5 : spdk_put_io_channel(ch);
853 : 5 : poll_threads();
854 : :
855 : 5 : spdk_io_device_unregister(&device, NULL);
856 : 5 : poll_threads();
857 : :
858 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
859 : 5 : free_threads();
860 : 5 : CU_ASSERT(TAILQ_EMPTY(&g_threads));
861 : 5 : }
862 : :
863 : : static void
864 : 5 : thread_exit_test(void)
865 : : {
866 : : struct spdk_thread *thread;
867 : : struct spdk_io_channel *ch;
868 : 4 : struct spdk_poller *poller1, *poller2;
869 : : void *ctx;
870 : 5 : bool done1 = false, done2 = false, poller1_run = false, poller2_run = false;
871 : : int rc __attribute__((unused));
872 : :
873 : 5 : MOCK_SET(spdk_get_ticks, 10);
874 : 5 : MOCK_SET(spdk_get_ticks_hz, 1);
875 : :
876 : 5 : allocate_threads(4);
877 : :
878 : : /* Test if all pending messages are reaped for the exiting thread, and the
879 : : * thread moves to the exited state.
880 : : */
881 : 5 : set_thread(0);
882 : 5 : thread = spdk_get_thread();
883 : :
884 : : /* Sending message to thread 0 will be accepted. */
885 : 5 : rc = spdk_thread_send_msg(thread, send_msg_cb, &done1);
886 : 5 : CU_ASSERT(rc == 0);
887 [ - + ]: 5 : CU_ASSERT(!done1);
888 : :
889 : : /* Move thread 0 to the exiting state. */
890 : 5 : spdk_thread_exit(thread);
891 : :
892 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
893 : :
894 : : /* Sending message to thread 0 will be still accepted. */
895 : 5 : rc = spdk_thread_send_msg(thread, send_msg_cb, &done2);
896 : 5 : CU_ASSERT(rc == 0);
897 : :
898 : : /* Thread 0 will reap pending messages. */
899 : 5 : poll_thread(0);
900 [ - + ]: 5 : CU_ASSERT(done1 == true);
901 [ - + ]: 5 : CU_ASSERT(done2 == true);
902 : :
903 : : /* Thread 0 will move to the exited state. */
904 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == true);
905 : :
906 : : /* Test releasing I/O channel is reaped even after the thread moves to
907 : : * the exiting state
908 : : */
909 : 5 : set_thread(1);
910 : :
911 : 5 : spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);
912 : :
913 : 5 : g_create_cb_calls = 0;
914 : 5 : ch = spdk_get_io_channel(&g_device1);
915 : 5 : CU_ASSERT(g_create_cb_calls == 1);
916 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
917 : :
918 : 5 : ctx = spdk_io_channel_get_ctx(ch);
919 : 5 : CU_ASSERT(*(uint64_t *)ctx == g_ctx1);
920 : :
921 : 5 : g_destroy_cb_calls = 0;
922 : 5 : spdk_put_io_channel(ch);
923 : :
924 : 5 : thread = spdk_get_thread();
925 : 5 : spdk_thread_exit(thread);
926 : :
927 : : /* Thread 1 will not move to the exited state yet because I/O channel release
928 : : * does not complete yet.
929 : : */
930 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
931 : :
932 : : /* Thread 1 will be able to get the another reference of I/O channel
933 : : * even after the thread moves to the exiting state.
934 : : */
935 : 5 : g_create_cb_calls = 0;
936 : 5 : ch = spdk_get_io_channel(&g_device1);
937 : :
938 : 5 : CU_ASSERT(g_create_cb_calls == 0);
939 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
940 : :
941 : 5 : ctx = spdk_io_channel_get_ctx(ch);
942 : 5 : CU_ASSERT(*(uint64_t *)ctx == g_ctx1);
943 : :
944 : 5 : spdk_put_io_channel(ch);
945 : :
946 : 5 : poll_threads();
947 : 5 : CU_ASSERT(g_destroy_cb_calls == 1);
948 : :
949 : : /* Thread 1 will move to the exited state after I/O channel is released.
950 : : * are released.
951 : : */
952 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == true);
953 : :
954 : 5 : spdk_io_device_unregister(&g_device1, NULL);
955 : 5 : poll_threads();
956 : :
957 : : /* Test if unregistering poller is reaped for the exiting thread, and the
958 : : * thread moves to the exited thread.
959 : : */
960 : 5 : set_thread(2);
961 : 5 : thread = spdk_get_thread();
962 : :
963 : 5 : poller1 = spdk_poller_register(poller_run_done, &poller1_run, 0);
964 : 5 : CU_ASSERT(poller1 != NULL);
965 : :
966 : 5 : spdk_poller_unregister(&poller1);
967 : :
968 : 5 : spdk_thread_exit(thread);
969 : :
970 : 5 : poller2 = spdk_poller_register(poller_run_done, &poller2_run, 0);
971 : :
972 : 5 : poll_threads();
973 : :
974 [ - + ]: 5 : CU_ASSERT(poller1_run == false);
975 [ - + ]: 5 : CU_ASSERT(poller2_run == true);
976 : :
977 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
978 : :
979 : 5 : spdk_poller_unregister(&poller2);
980 : :
981 : 5 : poll_threads();
982 : :
983 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == true);
984 : :
985 : : /* Test if the exiting thread is exited forcefully after timeout. */
986 : 5 : set_thread(3);
987 : 5 : thread = spdk_get_thread();
988 : :
989 : 5 : poller1 = spdk_poller_register(poller_run_done, &poller1_run, 0);
990 : 5 : CU_ASSERT(poller1 != NULL);
991 : :
992 : 5 : spdk_thread_exit(thread);
993 : :
994 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
995 : :
996 : 5 : MOCK_SET(spdk_get_ticks, 11);
997 : :
998 : 5 : poll_threads();
999 : :
1000 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
1001 : :
1002 : : /* Cause timeout forcefully. */
1003 : 5 : MOCK_SET(spdk_get_ticks, 15);
1004 : :
1005 : 5 : poll_threads();
1006 : :
1007 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == true);
1008 : :
1009 : 5 : spdk_poller_unregister(&poller1);
1010 : :
1011 : 5 : poll_threads();
1012 : :
1013 [ - - - + ]: 5 : MOCK_CLEAR(spdk_get_ticks);
1014 [ - - - + ]: 5 : MOCK_CLEAR(spdk_get_ticks_hz);
1015 : :
1016 : 5 : free_threads();
1017 : 5 : }
1018 : :
1019 : : static int
1020 : 10 : poller_run_idle(void *ctx)
1021 : : {
1022 : 10 : uint64_t delay_us = (uint64_t)ctx;
1023 : :
1024 : 10 : spdk_delay_us(delay_us);
1025 : :
1026 : 10 : return 0;
1027 : : }
1028 : :
1029 : : static int
1030 : 10 : poller_run_busy(void *ctx)
1031 : : {
1032 : 10 : uint64_t delay_us = (uint64_t)ctx;
1033 : :
1034 : 10 : spdk_delay_us(delay_us);
1035 : :
1036 : 10 : return 1;
1037 : : }
1038 : :
1039 : : static void
1040 : 5 : thread_update_stats_test(void)
1041 : : {
1042 : 4 : struct spdk_poller *poller;
1043 : : struct spdk_thread *thread;
1044 : :
1045 : 5 : MOCK_SET(spdk_get_ticks, 10);
1046 : :
1047 : 5 : allocate_threads(1);
1048 : :
1049 : 5 : set_thread(0);
1050 : 5 : thread = spdk_get_thread();
1051 : :
1052 : 5 : CU_ASSERT(thread->tsc_last == 10);
1053 : 5 : CU_ASSERT(thread->stats.idle_tsc == 0);
1054 : 5 : CU_ASSERT(thread->stats.busy_tsc == 0);
1055 : :
1056 : : /* Test if idle_tsc is updated expectedly. */
1057 : 5 : poller = spdk_poller_register(poller_run_idle, (void *)1000, 0);
1058 : 5 : CU_ASSERT(poller != NULL);
1059 : :
1060 : 5 : spdk_delay_us(100);
1061 : :
1062 : 5 : poll_thread_times(0, 1);
1063 : :
1064 : 5 : CU_ASSERT(thread->tsc_last == 1110);
1065 : 5 : CU_ASSERT(thread->stats.idle_tsc == 1000);
1066 : 5 : CU_ASSERT(thread->stats.busy_tsc == 0);
1067 : :
1068 : 5 : spdk_delay_us(100);
1069 : :
1070 : 5 : poll_thread_times(0, 1);
1071 : :
1072 : 5 : CU_ASSERT(thread->tsc_last == 2210);
1073 : 5 : CU_ASSERT(thread->stats.idle_tsc == 2000);
1074 : 5 : CU_ASSERT(thread->stats.busy_tsc == 0);
1075 : :
1076 : 5 : spdk_poller_unregister(&poller);
1077 : :
1078 : : /* Test if busy_tsc is updated expectedly. */
1079 : 5 : poller = spdk_poller_register(poller_run_busy, (void *)100000, 0);
1080 : 5 : CU_ASSERT(poller != NULL);
1081 : :
1082 : 5 : spdk_delay_us(10000);
1083 : :
1084 : 5 : poll_thread_times(0, 1);
1085 : :
1086 : 5 : CU_ASSERT(thread->tsc_last == 112210);
1087 : 5 : CU_ASSERT(thread->stats.idle_tsc == 2000);
1088 : 5 : CU_ASSERT(thread->stats.busy_tsc == 100000);
1089 : :
1090 : 5 : spdk_delay_us(10000);
1091 : :
1092 : 5 : poll_thread_times(0, 1);
1093 : :
1094 : 5 : CU_ASSERT(thread->tsc_last == 222210);
1095 : 5 : CU_ASSERT(thread->stats.idle_tsc == 2000);
1096 : 5 : CU_ASSERT(thread->stats.busy_tsc == 200000);
1097 : :
1098 : 5 : spdk_poller_unregister(&poller);
1099 : :
1100 [ - - - + ]: 5 : MOCK_CLEAR(spdk_get_ticks);
1101 : :
1102 : 5 : free_threads();
1103 : 5 : }
1104 : :
1105 : : struct ut_nested_ch {
1106 : : struct spdk_io_channel *child;
1107 : : struct spdk_poller *poller;
1108 : : };
1109 : :
1110 : : struct ut_nested_dev {
1111 : : struct ut_nested_dev *child;
1112 : : };
1113 : :
1114 : : static int
1115 : 30 : ut_null_poll(void *ctx)
1116 : : {
1117 : 30 : return -1;
1118 : : }
1119 : :
1120 : : static int
1121 : 15 : ut_nested_ch_create_cb(void *io_device, void *ctx_buf)
1122 : : {
1123 : 15 : struct ut_nested_ch *_ch = ctx_buf;
1124 : 15 : struct ut_nested_dev *_dev = io_device;
1125 : : struct ut_nested_dev *_child;
1126 : :
1127 : 15 : _child = _dev->child;
1128 : :
1129 [ + + ]: 15 : if (_child != NULL) {
1130 : 10 : _ch->child = spdk_get_io_channel(_child);
1131 [ - + ]: 10 : SPDK_CU_ASSERT_FATAL(_ch->child != NULL);
1132 : : } else {
1133 : 5 : _ch->child = NULL;
1134 : : }
1135 : :
1136 : 15 : _ch->poller = spdk_poller_register(ut_null_poll, NULL, 0);
1137 [ - + ]: 15 : SPDK_CU_ASSERT_FATAL(_ch->poller != NULL);
1138 : :
1139 : 15 : return 0;
1140 : : }
1141 : :
1142 : : static void
1143 : 15 : ut_nested_ch_destroy_cb(void *io_device, void *ctx_buf)
1144 : : {
1145 : 15 : struct ut_nested_ch *_ch = ctx_buf;
1146 : : struct spdk_io_channel *child;
1147 : :
1148 : 15 : child = _ch->child;
1149 [ + + ]: 15 : if (child != NULL) {
1150 : 10 : spdk_put_io_channel(child);
1151 : : }
1152 : :
1153 : 15 : spdk_poller_unregister(&_ch->poller);
1154 : 15 : }
1155 : :
1156 : : static void
1157 : 15 : ut_check_nested_ch_create(struct spdk_io_channel *ch, struct io_device *dev)
1158 : : {
1159 : 15 : CU_ASSERT(ch->ref == 1);
1160 : 15 : CU_ASSERT(ch->dev == dev);
1161 : 15 : CU_ASSERT(dev->refcnt == 1);
1162 : 15 : }
1163 : :
1164 : : static void
1165 : 15 : ut_check_nested_ch_destroy_pre(struct spdk_io_channel *ch, struct io_device *dev)
1166 : : {
1167 : 15 : CU_ASSERT(ch->ref == 0);
1168 : 15 : CU_ASSERT(ch->destroy_ref == 1);
1169 : 15 : CU_ASSERT(dev->refcnt == 1);
1170 : 15 : }
1171 : :
1172 : : static void
1173 : 15 : ut_check_nested_ch_destroy_post(struct io_device *dev)
1174 : : {
1175 : 15 : CU_ASSERT(dev->refcnt == 0);
1176 : 15 : }
1177 : :
1178 : : static void
1179 : 20 : ut_check_nested_poller_register(struct spdk_poller *poller)
1180 : : {
1181 [ - + ]: 20 : SPDK_CU_ASSERT_FATAL(poller != NULL);
1182 : 20 : }
1183 : :
1184 : : static void
1185 : 5 : nested_channel(void)
1186 : : {
1187 : 4 : struct ut_nested_dev _dev1, _dev2, _dev3;
1188 : : struct ut_nested_ch *_ch1, *_ch2, *_ch3;
1189 : : struct io_device *dev1, *dev2, *dev3;
1190 : : struct spdk_io_channel *ch1, *ch2, *ch3;
1191 : 4 : struct spdk_poller *poller;
1192 : : struct spdk_thread *thread;
1193 : :
1194 : 5 : allocate_threads(1);
1195 : 5 : set_thread(0);
1196 : :
1197 : 5 : thread = spdk_get_thread();
1198 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
1199 : :
1200 : 5 : _dev1.child = &_dev2;
1201 : 5 : _dev2.child = &_dev3;
1202 : 5 : _dev3.child = NULL;
1203 : :
1204 : 5 : spdk_io_device_register(&_dev1, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
1205 : : sizeof(struct ut_nested_ch), "dev1");
1206 : 5 : spdk_io_device_register(&_dev2, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
1207 : : sizeof(struct ut_nested_ch), "dev2");
1208 : 5 : spdk_io_device_register(&_dev3, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
1209 : : sizeof(struct ut_nested_ch), "dev3");
1210 : :
1211 : 5 : dev1 = io_device_get(&_dev1);
1212 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev1 != NULL);
1213 : 5 : dev2 = io_device_get(&_dev2);
1214 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev2 != NULL);
1215 : 5 : dev3 = io_device_get(&_dev3);
1216 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev3 != NULL);
1217 : :
1218 : : /* A single call spdk_get_io_channel() to dev1 will also create channels
1219 : : * to dev2 and dev3 continuously. Pollers will be registered together.
1220 : : */
1221 : 5 : ch1 = spdk_get_io_channel(&_dev1);
1222 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1223 : :
1224 : 5 : _ch1 = spdk_io_channel_get_ctx(ch1);
1225 : 5 : ch2 = _ch1->child;
1226 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1227 : :
1228 : 5 : _ch2 = spdk_io_channel_get_ctx(ch2);
1229 : 5 : ch3 = _ch2->child;
1230 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch3 != NULL);
1231 : :
1232 : 5 : _ch3 = spdk_io_channel_get_ctx(ch3);
1233 : 5 : CU_ASSERT(_ch3->child == NULL);
1234 : :
1235 : 5 : ut_check_nested_ch_create(ch1, dev1);
1236 : 5 : ut_check_nested_ch_create(ch2, dev2);
1237 : 5 : ut_check_nested_ch_create(ch3, dev3);
1238 : :
1239 : 5 : poller = spdk_poller_register(ut_null_poll, NULL, 0);
1240 : :
1241 : 5 : ut_check_nested_poller_register(poller);
1242 : 5 : ut_check_nested_poller_register(_ch1->poller);
1243 : 5 : ut_check_nested_poller_register(_ch2->poller);
1244 : 5 : ut_check_nested_poller_register(_ch3->poller);
1245 : :
1246 : 5 : spdk_poller_unregister(&poller);
1247 : 5 : poll_thread_times(0, 1);
1248 : :
1249 : : /* A single call spdk_put_io_channel() to dev1 will also destroy channels
1250 : : * to dev2 and dev3 continuously. Pollers will be unregistered together.
1251 : : */
1252 : 5 : spdk_put_io_channel(ch1);
1253 : :
1254 : : /* Start exiting the current thread after unregistering the non-nested
1255 : : * I/O channel.
1256 : : */
1257 : 5 : spdk_thread_exit(thread);
1258 : :
1259 : 5 : ut_check_nested_ch_destroy_pre(ch1, dev1);
1260 : 5 : poll_thread_times(0, 1);
1261 : 5 : ut_check_nested_ch_destroy_post(dev1);
1262 : :
1263 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
1264 : :
1265 : 5 : ut_check_nested_ch_destroy_pre(ch2, dev2);
1266 : 5 : poll_thread_times(0, 1);
1267 : 5 : ut_check_nested_ch_destroy_post(dev2);
1268 : :
1269 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == false);
1270 : :
1271 : 5 : ut_check_nested_ch_destroy_pre(ch3, dev3);
1272 : 5 : poll_thread_times(0, 1);
1273 : 5 : ut_check_nested_ch_destroy_post(dev3);
1274 : :
1275 : 5 : CU_ASSERT(spdk_thread_is_exited(thread) == true);
1276 : :
1277 : 5 : spdk_io_device_unregister(&_dev1, NULL);
1278 : 5 : spdk_io_device_unregister(&_dev2, NULL);
1279 : 5 : spdk_io_device_unregister(&_dev3, NULL);
1280 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
1281 : :
1282 : 5 : free_threads();
1283 : 5 : CU_ASSERT(TAILQ_EMPTY(&g_threads));
1284 : 5 : }
1285 : :
1286 : : static int
1287 : 10 : create_cb2(void *io_device, void *ctx_buf)
1288 : : {
1289 : 10 : uint64_t *devcnt = (uint64_t *)io_device;
1290 : :
1291 : 10 : *devcnt += 1;
1292 : :
1293 : 10 : return 0;
1294 : : }
1295 : :
1296 : : static void
1297 : 10 : destroy_cb2(void *io_device, void *ctx_buf)
1298 : : {
1299 : 10 : uint64_t *devcnt = (uint64_t *)io_device;
1300 : :
1301 : 10 : CU_ASSERT(*devcnt > 0);
1302 : 10 : *devcnt -= 1;
1303 : 10 : }
1304 : :
1305 : : static void
1306 : 5 : unregister_cb2(void *io_device)
1307 : : {
1308 : 5 : uint64_t *devcnt = (uint64_t *)io_device;
1309 : :
1310 : 5 : CU_ASSERT(*devcnt == 0);
1311 : 5 : }
1312 : :
1313 : : static void
1314 : 5 : device_unregister_and_thread_exit_race(void)
1315 : : {
1316 : 5 : uint64_t device = 0;
1317 : : struct spdk_io_channel *ch1, *ch2;
1318 : : struct spdk_thread *thread1, *thread2;
1319 : :
1320 : : /* Create two threads and each thread gets a channel from the same device. */
1321 : 5 : allocate_threads(2);
1322 : 5 : set_thread(0);
1323 : :
1324 : 5 : thread1 = spdk_get_thread();
1325 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread1 != NULL);
1326 : :
1327 : 5 : spdk_io_device_register(&device, create_cb2, destroy_cb2, sizeof(uint64_t), NULL);
1328 : :
1329 : 5 : ch1 = spdk_get_io_channel(&device);
1330 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1331 : :
1332 : 5 : set_thread(1);
1333 : :
1334 : 5 : thread2 = spdk_get_thread();
1335 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread2 != NULL);
1336 : :
1337 : 5 : ch2 = spdk_get_io_channel(&device);
1338 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1339 : :
1340 : 5 : set_thread(0);
1341 : :
1342 : : /* Move thread 0 to the exiting state, but it should keep exiting until two channels
1343 : : * and a device are released.
1344 : : */
1345 : 5 : spdk_thread_exit(thread1);
1346 : 5 : poll_thread(0);
1347 : :
1348 : 5 : spdk_put_io_channel(ch1);
1349 : :
1350 : 5 : spdk_io_device_unregister(&device, unregister_cb2);
1351 : 5 : poll_thread(0);
1352 : :
1353 : 5 : CU_ASSERT(spdk_thread_is_exited(thread1) == false);
1354 : :
1355 : 5 : set_thread(1);
1356 : :
1357 : : /* Move thread 1 to the exiting state, but it should keep exiting until its channel
1358 : : * is released.
1359 : : */
1360 : 5 : spdk_thread_exit(thread2);
1361 : 5 : poll_thread(1);
1362 : :
1363 : 5 : CU_ASSERT(spdk_thread_is_exited(thread2) == false);
1364 : :
1365 : 5 : spdk_put_io_channel(ch2);
1366 : 5 : poll_thread(1);
1367 : :
1368 : 5 : CU_ASSERT(spdk_thread_is_exited(thread1) == false);
1369 : 5 : CU_ASSERT(spdk_thread_is_exited(thread2) == true);
1370 : :
1371 : 5 : poll_thread(0);
1372 : :
1373 : 5 : CU_ASSERT(spdk_thread_is_exited(thread1) == true);
1374 : :
1375 : 5 : free_threads();
1376 : 5 : }
1377 : :
1378 : : static int
1379 : 55 : dummy_poller(void *arg)
1380 : : {
1381 : 55 : return SPDK_POLLER_IDLE;
1382 : : }
1383 : :
1384 : : static void
1385 : 5 : cache_closest_timed_poller(void)
1386 : : {
1387 : : struct spdk_thread *thread;
1388 : 4 : struct spdk_poller *poller1, *poller2, *poller3, *tmp;
1389 : :
1390 : 5 : allocate_threads(1);
1391 : 5 : set_thread(0);
1392 : :
1393 : 5 : thread = spdk_get_thread();
1394 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
1395 : :
1396 : 5 : poller1 = spdk_poller_register(dummy_poller, NULL, 1000);
1397 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller1 != NULL);
1398 : :
1399 : 5 : poller2 = spdk_poller_register(dummy_poller, NULL, 1500);
1400 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller2 != NULL);
1401 : :
1402 : 5 : poller3 = spdk_poller_register(dummy_poller, NULL, 1800);
1403 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller3 != NULL);
1404 : :
1405 : 5 : poll_threads();
1406 : :
1407 : : /* When multiple timed pollers are inserted, the cache should
1408 : : * have the closest timed poller.
1409 : : */
1410 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1411 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller1);
1412 : :
1413 : 5 : spdk_delay_us(1000);
1414 : 5 : poll_threads();
1415 : :
1416 : 5 : CU_ASSERT(thread->first_timed_poller == poller2);
1417 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller2);
1418 : :
1419 : : /* If we unregister a timed poller by spdk_poller_unregister()
1420 : : * when it is waiting, it is marked as being unregistered and
1421 : : * is actually unregistered when it is expired.
1422 : : *
1423 : : * Hence if we unregister the closest timed poller when it is waiting,
1424 : : * the cache is not updated to the next timed poller until it is expired.
1425 : : */
1426 : 5 : tmp = poller2;
1427 : :
1428 : 5 : spdk_poller_unregister(&poller2);
1429 : 5 : CU_ASSERT(poller2 == NULL);
1430 : :
1431 : 5 : spdk_delay_us(499);
1432 : 5 : poll_threads();
1433 : :
1434 : 5 : CU_ASSERT(thread->first_timed_poller == tmp);
1435 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == tmp);
1436 : :
1437 : 5 : spdk_delay_us(1);
1438 : 5 : poll_threads();
1439 : :
1440 : 5 : CU_ASSERT(thread->first_timed_poller == poller3);
1441 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller3);
1442 : :
1443 : : /* If we pause a timed poller by spdk_poller_pause() when it is waiting,
1444 : : * it is marked as being paused and is actually paused when it is expired.
1445 : : *
1446 : : * Hence if we pause the closest timed poller when it is waiting, the cache
1447 : : * is not updated to the next timed poller until it is expired.
1448 : : */
1449 : 5 : spdk_poller_pause(poller3);
1450 : :
1451 : 5 : spdk_delay_us(299);
1452 : 5 : poll_threads();
1453 : :
1454 : 5 : CU_ASSERT(thread->first_timed_poller == poller3);
1455 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller3);
1456 : :
1457 : 5 : spdk_delay_us(1);
1458 : 5 : poll_threads();
1459 : :
1460 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1461 : 5 : CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller1);
1462 : :
1463 : : /* After unregistering all timed pollers, the cache should
1464 : : * be NULL.
1465 : : */
1466 : 5 : spdk_poller_unregister(&poller1);
1467 : 5 : spdk_poller_unregister(&poller3);
1468 : :
1469 : 5 : spdk_delay_us(200);
1470 : 5 : poll_threads();
1471 : :
1472 : 5 : CU_ASSERT(thread->first_timed_poller == NULL);
1473 : 5 : CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
1474 : :
1475 : 5 : free_threads();
1476 : 5 : }
1477 : :
1478 : : static void
1479 : 5 : multi_timed_pollers_have_same_expiration(void)
1480 : : {
1481 : : struct spdk_thread *thread;
1482 : 4 : struct spdk_poller *poller1, *poller2, *poller3, *poller4, *tmp;
1483 : : uint64_t start_ticks;
1484 : :
1485 : 5 : allocate_threads(1);
1486 : 5 : set_thread(0);
1487 : :
1488 : 5 : thread = spdk_get_thread();
1489 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(thread != NULL);
1490 : :
1491 : : /*
1492 : : * case 1: multiple timed pollers have the same next_run_tick.
1493 : : */
1494 : 5 : start_ticks = spdk_get_ticks();
1495 : :
1496 : 5 : poller1 = spdk_poller_register(dummy_poller, NULL, 500);
1497 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller1 != NULL);
1498 : :
1499 : 5 : poller2 = spdk_poller_register(dummy_poller, NULL, 500);
1500 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller2 != NULL);
1501 : :
1502 : 5 : poller3 = spdk_poller_register(dummy_poller, NULL, 1000);
1503 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller3 != NULL);
1504 : :
1505 : 5 : poller4 = spdk_poller_register(dummy_poller, NULL, 1500);
1506 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller4 != NULL);
1507 : :
1508 : : /* poller1 and poller2 have the same next_run_tick but cache has poller1
1509 : : * because poller1 is registered earlier than poller2.
1510 : : */
1511 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1512 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
1513 : 5 : CU_ASSERT(poller2->next_run_tick == start_ticks + 500);
1514 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
1515 : 5 : CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
1516 : :
1517 : : /* after 500 usec, poller1 and poller2 are expired. */
1518 : 5 : spdk_delay_us(500);
1519 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 500);
1520 : 5 : poll_threads();
1521 : :
1522 : : /* poller1, poller2, and poller3 have the same next_run_tick but cache
1523 : : * has poller3 because poller3 is not expired yet.
1524 : : */
1525 : 5 : CU_ASSERT(thread->first_timed_poller == poller3);
1526 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
1527 : 5 : CU_ASSERT(poller2->next_run_tick == start_ticks + 1000);
1528 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
1529 : 5 : CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
1530 : :
1531 : : /* after 500 usec, poller1, poller2, and poller3 are expired. */
1532 : 5 : spdk_delay_us(500);
1533 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 1000);
1534 : 5 : poll_threads();
1535 : :
1536 : : /* poller1, poller2, and poller4 have the same next_run_tick but cache
1537 : : * has poller4 because poller4 is not expired yet.
1538 : : */
1539 : 5 : CU_ASSERT(thread->first_timed_poller == poller4);
1540 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 1500);
1541 : 5 : CU_ASSERT(poller2->next_run_tick == start_ticks + 1500);
1542 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 2000);
1543 : 5 : CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
1544 : :
1545 : : /* after 500 usec, poller1, poller2, and poller4 are expired. */
1546 : 5 : spdk_delay_us(500);
1547 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 1500);
1548 : 5 : poll_threads();
1549 : :
1550 : : /* poller1, poller2, and poller3 have the same next_run_tick but cache
1551 : : * has poller3 because poller3 is updated earlier than poller1 and poller2.
1552 : : */
1553 : 5 : CU_ASSERT(thread->first_timed_poller == poller3);
1554 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 2000);
1555 : 5 : CU_ASSERT(poller2->next_run_tick == start_ticks + 2000);
1556 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 2000);
1557 : 5 : CU_ASSERT(poller4->next_run_tick == start_ticks + 3000);
1558 : :
1559 : 5 : spdk_poller_unregister(&poller1);
1560 : 5 : spdk_poller_unregister(&poller2);
1561 : 5 : spdk_poller_unregister(&poller3);
1562 : 5 : spdk_poller_unregister(&poller4);
1563 : :
1564 : 5 : spdk_delay_us(1500);
1565 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 3000);
1566 : 5 : poll_threads();
1567 : :
1568 : 5 : CU_ASSERT(thread->first_timed_poller == NULL);
1569 : 5 : CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
1570 : :
1571 : : /*
1572 : : * case 2: unregister timed pollers while multiple timed pollers are registered.
1573 : : */
1574 : 5 : start_ticks = spdk_get_ticks();
1575 : :
1576 : 5 : poller1 = spdk_poller_register(dummy_poller, NULL, 500);
1577 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller1 != NULL);
1578 : :
1579 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1580 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
1581 : :
1582 : : /* after 250 usec, register poller2 and poller3. */
1583 : 5 : spdk_delay_us(250);
1584 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 250);
1585 : :
1586 : 5 : poller2 = spdk_poller_register(dummy_poller, NULL, 500);
1587 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller2 != NULL);
1588 : :
1589 : 5 : poller3 = spdk_poller_register(dummy_poller, NULL, 750);
1590 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(poller3 != NULL);
1591 : :
1592 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1593 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
1594 : 5 : CU_ASSERT(poller2->next_run_tick == start_ticks + 750);
1595 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
1596 : :
1597 : : /* unregister poller2 which is not the closest. */
1598 : 5 : tmp = poller2;
1599 : 5 : spdk_poller_unregister(&poller2);
1600 : :
1601 : : /* after 250 usec, poller1 is expired. */
1602 : 5 : spdk_delay_us(250);
1603 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 500);
1604 : 5 : poll_threads();
1605 : :
1606 : : /* poller2 is not unregistered yet because it is not expired. */
1607 : 5 : CU_ASSERT(thread->first_timed_poller == tmp);
1608 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
1609 : 5 : CU_ASSERT(tmp->next_run_tick == start_ticks + 750);
1610 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
1611 : :
1612 : 5 : spdk_delay_us(250);
1613 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 750);
1614 : 5 : poll_threads();
1615 : :
1616 : 5 : CU_ASSERT(thread->first_timed_poller == poller3);
1617 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
1618 : 5 : CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
1619 : :
1620 : 5 : spdk_poller_unregister(&poller3);
1621 : :
1622 : 5 : spdk_delay_us(250);
1623 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 1000);
1624 : 5 : poll_threads();
1625 : :
1626 : 5 : CU_ASSERT(thread->first_timed_poller == poller1);
1627 : 5 : CU_ASSERT(poller1->next_run_tick == start_ticks + 1500);
1628 : :
1629 : 5 : spdk_poller_unregister(&poller1);
1630 : :
1631 : 5 : spdk_delay_us(500);
1632 : 5 : CU_ASSERT(spdk_get_ticks() == start_ticks + 1500);
1633 : 5 : poll_threads();
1634 : :
1635 : 5 : CU_ASSERT(thread->first_timed_poller == NULL);
1636 : 5 : CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
1637 : :
1638 : 5 : free_threads();
1639 : 5 : }
1640 : :
1641 : : static int
1642 : 35 : dummy_create_cb(void *io_device, void *ctx_buf)
1643 : : {
1644 : 35 : return 0;
1645 : : }
1646 : :
1647 : : static void
1648 : 35 : dummy_destroy_cb(void *io_device, void *ctx_buf)
1649 : : {
1650 : 35 : }
1651 : :
1652 : : /* We had a bug that the compare function for the io_device tree
1653 : : * did not work as expected because subtraction caused overflow
1654 : : * when the difference between two keys was more than 32 bits.
1655 : : * This test case verifies the fix for the bug.
1656 : : */
1657 : : static void
1658 : 5 : io_device_lookup(void)
1659 : : {
1660 : 4 : struct io_device dev1, dev2, *dev;
1661 : : struct spdk_io_channel *ch;
1662 : :
1663 : : /* The compare function io_device_cmp() had a overflow bug.
1664 : : * Verify the fix first.
1665 : : */
1666 : 5 : dev1.io_device = (void *)0x7FFFFFFF;
1667 : 5 : dev2.io_device = NULL;
1668 : 5 : CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
1669 : 5 : CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
1670 : :
1671 : : /* Check if overflow due to 32 bits does not occur. */
1672 : 5 : dev1.io_device = (void *)0x80000000;
1673 : 5 : CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
1674 : 5 : CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
1675 : :
1676 : 5 : dev1.io_device = (void *)0x100000000;
1677 : 5 : CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
1678 : 5 : CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
1679 : :
1680 : 5 : dev1.io_device = (void *)0x8000000000000000;
1681 : 5 : CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
1682 : 5 : CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
1683 : :
1684 : 5 : allocate_threads(1);
1685 : 5 : set_thread(0);
1686 : :
1687 : 5 : spdk_io_device_register((void *)0x1, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1688 : 5 : spdk_io_device_register((void *)0x7FFFFFFF, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1689 : 5 : spdk_io_device_register((void *)0x80000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1690 : 5 : spdk_io_device_register((void *)0x100000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1691 : 5 : spdk_io_device_register((void *)0x8000000000000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1692 : 5 : spdk_io_device_register((void *)0x8000000100000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1693 : 5 : spdk_io_device_register((void *)UINT64_MAX, dummy_create_cb, dummy_destroy_cb, 0, NULL);
1694 : :
1695 : : /* RB_MIN and RB_NEXT should return devs in ascending order by addresses.
1696 : : * RB_FOREACH uses RB_MIN and RB_NEXT internally.
1697 : : */
1698 : 5 : dev = RB_MIN(io_device_tree, &g_io_devices);
1699 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1700 : 5 : CU_ASSERT(dev->io_device == (void *)0x1);
1701 : :
1702 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1703 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1704 : 5 : CU_ASSERT(dev->io_device == (void *)0x7FFFFFFF);
1705 : :
1706 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1707 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1708 : 5 : CU_ASSERT(dev->io_device == (void *)0x80000000);
1709 : :
1710 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1711 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1712 : 5 : CU_ASSERT(dev->io_device == (void *)0x100000000);
1713 : :
1714 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1715 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1716 : 5 : CU_ASSERT(dev->io_device == (void *)0x8000000000000000);
1717 : :
1718 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1719 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1720 : 5 : CU_ASSERT(dev->io_device == (void *)0x8000000100000000);
1721 : :
1722 : 5 : dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
1723 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(dev != NULL);
1724 : 5 : CU_ASSERT(dev->io_device == (void *)UINT64_MAX);
1725 : :
1726 : : /* Verify spdk_get_io_channel() creates io_channels associated with the
1727 : : * correct io_devices.
1728 : : */
1729 : 5 : ch = spdk_get_io_channel((void *)0x1);
1730 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1731 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x1);
1732 : 5 : spdk_put_io_channel(ch);
1733 : :
1734 : 5 : ch = spdk_get_io_channel((void *)0x7FFFFFFF);
1735 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1736 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x7FFFFFFF);
1737 : 5 : spdk_put_io_channel(ch);
1738 : :
1739 : 5 : ch = spdk_get_io_channel((void *)0x80000000);
1740 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1741 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x80000000);
1742 : 5 : spdk_put_io_channel(ch);
1743 : :
1744 : 5 : ch = spdk_get_io_channel((void *)0x100000000);
1745 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1746 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x100000000);
1747 : 5 : spdk_put_io_channel(ch);
1748 : :
1749 : 5 : ch = spdk_get_io_channel((void *)0x8000000000000000);
1750 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1751 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x8000000000000000);
1752 : 5 : spdk_put_io_channel(ch);
1753 : :
1754 : 5 : ch = spdk_get_io_channel((void *)0x8000000100000000);
1755 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1756 : 5 : CU_ASSERT(ch->dev->io_device == (void *)0x8000000100000000);
1757 : 5 : spdk_put_io_channel(ch);
1758 : :
1759 : 5 : ch = spdk_get_io_channel((void *)UINT64_MAX);
1760 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1761 : 5 : CU_ASSERT(ch->dev->io_device == (void *)UINT64_MAX);
1762 : 5 : spdk_put_io_channel(ch);
1763 : :
1764 : 5 : poll_threads();
1765 : :
1766 : 5 : spdk_io_device_unregister((void *)0x1, NULL);
1767 : 5 : spdk_io_device_unregister((void *)0x7FFFFFFF, NULL);
1768 : 5 : spdk_io_device_unregister((void *)0x80000000, NULL);
1769 : 5 : spdk_io_device_unregister((void *)0x100000000, NULL);
1770 : 5 : spdk_io_device_unregister((void *)0x8000000000000000, NULL);
1771 : 5 : spdk_io_device_unregister((void *)0x8000000100000000, NULL);
1772 : 5 : spdk_io_device_unregister((void *)UINT64_MAX, NULL);
1773 : :
1774 : 5 : poll_threads();
1775 : :
1776 : 5 : CU_ASSERT(RB_EMPTY(&g_io_devices));
1777 : :
1778 : 5 : free_threads();
1779 : 5 : }
1780 : :
1781 : : static enum spin_error g_spin_err;
1782 : : static uint32_t g_spin_err_count = 0;
1783 : :
1784 : : static void
1785 : 30 : ut_track_abort(enum spin_error err)
1786 : : {
1787 : 30 : g_spin_err = err;
1788 : 30 : g_spin_err_count++;
1789 : 30 : }
1790 : :
1791 : : static void
1792 : 5 : spdk_spin(void)
1793 : : {
1794 : 4 : struct spdk_spinlock lock;
1795 : :
1796 : 5 : g_spin_abort_fn = ut_track_abort;
1797 : :
1798 : : /* Do not need to be on an SPDK thread to initialize an spdk_spinlock */
1799 : 5 : g_spin_err_count = 0;
1800 : 5 : spdk_spin_init(&lock);
1801 : 5 : CU_ASSERT(g_spin_err_count == 0);
1802 : :
1803 : : /* Trying to take a lock while not on an SPDK thread is an error */
1804 : 5 : g_spin_err_count = 0;
1805 : 5 : spdk_spin_lock(&lock);
1806 : 5 : CU_ASSERT(g_spin_err_count == 1);
1807 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_NOT_SPDK_THREAD);
1808 : :
1809 : : /* Trying to check if a lock is held while not on an SPDK thread is an error */
1810 : 5 : g_spin_err_count = 0;
1811 : 5 : spdk_spin_held(&lock);
1812 : 5 : CU_ASSERT(g_spin_err_count == 1);
1813 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_NOT_SPDK_THREAD);
1814 : :
1815 : : /* Do not need to be on an SPDK thread to destroy an spdk_spinlock */
1816 : 5 : g_spin_err_count = 0;
1817 : 5 : spdk_spin_destroy(&lock);
1818 : 5 : CU_ASSERT(g_spin_err_count == 0);
1819 : :
1820 : 5 : allocate_threads(2);
1821 : 5 : set_thread(0);
1822 : :
1823 : : /* Can initialize an spdk_spinlock on an SPDK thread */
1824 : 5 : g_spin_err_count = 0;
1825 : 5 : spdk_spin_init(&lock);
1826 : 5 : CU_ASSERT(g_spin_err_count == 0);
1827 : :
1828 : : /* Can take spinlock */
1829 : 5 : g_spin_err_count = 0;
1830 : 5 : spdk_spin_lock(&lock);
1831 : 5 : CU_ASSERT(g_spin_err_count == 0);
1832 : :
1833 : : /* Can release spinlock */
1834 : 5 : g_spin_err_count = 0;
1835 : 5 : spdk_spin_unlock(&lock);
1836 : 5 : CU_ASSERT(g_spin_err_count == 0);
1837 : :
1838 : : /* Deadlock detected */
1839 : 5 : g_spin_err_count = 0;
1840 : 5 : g_spin_err = SPIN_ERR_NONE;
1841 : 5 : spdk_spin_lock(&lock);
1842 : 5 : CU_ASSERT(g_spin_err_count == 0);
1843 : 5 : spdk_spin_lock(&lock);
1844 : 5 : CU_ASSERT(g_spin_err_count == 1);
1845 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_DEADLOCK);
1846 : :
1847 : : /* Cannot unlock from wrong thread */
1848 : 5 : set_thread(1);
1849 : 5 : g_spin_err_count = 0;
1850 : 5 : spdk_spin_unlock(&lock);
1851 : 5 : CU_ASSERT(g_spin_err_count == 1);
1852 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_WRONG_THREAD);
1853 : :
1854 : : /* Get back to a known good state */
1855 : 5 : set_thread(0);
1856 : 5 : g_spin_err_count = 0;
1857 : 5 : spdk_spin_unlock(&lock);
1858 : 5 : CU_ASSERT(g_spin_err_count == 0);
1859 : :
1860 : : /* Cannot release the same lock twice */
1861 : 5 : g_spin_err_count = 0;
1862 : 5 : spdk_spin_lock(&lock);
1863 : 5 : CU_ASSERT(g_spin_err_count == 0);
1864 : 5 : spdk_spin_unlock(&lock);
1865 : 5 : CU_ASSERT(g_spin_err_count == 0);
1866 : 5 : spdk_spin_unlock(&lock);
1867 : 5 : CU_ASSERT(g_spin_err_count == 1);
1868 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_WRONG_THREAD);
1869 : :
1870 : : /* A lock that is not held is properly recognized */
1871 : 5 : g_spin_err_count = 0;
1872 : 5 : CU_ASSERT(!spdk_spin_held(&lock));
1873 : 5 : CU_ASSERT(g_spin_err_count == 0);
1874 : :
1875 : : /* A lock that is held is recognized as held by only the thread that holds it. */
1876 : 5 : set_thread(1);
1877 : 5 : g_spin_err_count = 0;
1878 : 5 : spdk_spin_lock(&lock);
1879 : 5 : CU_ASSERT(g_spin_err_count == 0);
1880 : 5 : CU_ASSERT(spdk_spin_held(&lock));
1881 : 5 : CU_ASSERT(g_spin_err_count == 0);
1882 : 5 : set_thread(0);
1883 : 5 : CU_ASSERT(!spdk_spin_held(&lock));
1884 : 5 : CU_ASSERT(g_spin_err_count == 0);
1885 : :
1886 : : /* After releasing, no one thinks it is held */
1887 : 5 : set_thread(1);
1888 : 5 : spdk_spin_unlock(&lock);
1889 : 5 : CU_ASSERT(g_spin_err_count == 0);
1890 : 5 : CU_ASSERT(!spdk_spin_held(&lock));
1891 : 5 : CU_ASSERT(g_spin_err_count == 0);
1892 : 5 : set_thread(0);
1893 : 5 : CU_ASSERT(!spdk_spin_held(&lock));
1894 : 5 : CU_ASSERT(g_spin_err_count == 0);
1895 : :
1896 : : /* Destroying a lock that is held is an error. */
1897 : 5 : set_thread(0);
1898 : 5 : g_spin_err_count = 0;
1899 : 5 : spdk_spin_lock(&lock);
1900 : 5 : CU_ASSERT(g_spin_err_count == 0);
1901 : 5 : spdk_spin_destroy(&lock);
1902 : 5 : CU_ASSERT(g_spin_err_count == 1);
1903 : 5 : CU_ASSERT(g_spin_err == SPIN_ERR_LOCK_HELD);
1904 : 5 : g_spin_err_count = 0;
1905 : 5 : spdk_spin_unlock(&lock);
1906 : 5 : CU_ASSERT(g_spin_err_count == 0);
1907 : :
1908 : : /* Clean up */
1909 : 5 : g_spin_err_count = 0;
1910 : 5 : spdk_spin_destroy(&lock);
1911 : 5 : CU_ASSERT(g_spin_err_count == 0);
1912 : 5 : free_threads();
1913 : 5 : g_spin_abort_fn = __posix_abort;
1914 : 5 : }
1915 : :
1916 : : static void
1917 : 5 : for_each_channel_and_thread_exit_race(void)
1918 : : {
1919 : : struct spdk_io_channel *ch1, *ch2;
1920 : : struct spdk_thread *thread0;
1921 : 5 : int ch_count = 0;
1922 : 5 : int msg_count = 0;
1923 : :
1924 : 5 : allocate_threads(3);
1925 : 5 : set_thread(0);
1926 : 5 : spdk_io_device_register(&ch_count, channel_create, channel_destroy, sizeof(int), NULL);
1927 : 5 : set_thread(1);
1928 : 5 : ch1 = spdk_get_io_channel(&ch_count);
1929 : 5 : set_thread(2);
1930 : 5 : ch2 = spdk_get_io_channel(&ch_count);
1931 : 5 : CU_ASSERT(ch_count == 2);
1932 : :
1933 : : /*
1934 : : * Test one race condition between spdk_thread_exit() and spdk_for_each_channel().
1935 : : *
1936 : : * thread 0 does not have io_channel and calls spdk_thread_exit() immediately
1937 : : * after spdk_for_each_channel(). In this case, thread 0 should exit after
1938 : : * spdk_for_each_channel() completes.
1939 : : */
1940 : :
1941 : 5 : set_thread(0);
1942 : 5 : thread0 = spdk_get_thread();
1943 : :
1944 : 5 : CU_ASSERT(thread0->for_each_count == 0);
1945 : :
1946 : 5 : spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
1947 : 5 : CU_ASSERT(msg_count == 0);
1948 : 5 : CU_ASSERT(thread0->for_each_count == 1);
1949 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_RUNNING);
1950 : :
1951 : 5 : spdk_thread_exit(thread0);
1952 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITING);
1953 : :
1954 : 5 : poll_threads();
1955 : 5 : CU_ASSERT(msg_count == 3);
1956 : 5 : CU_ASSERT(thread0->for_each_count == 0);
1957 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITED);
1958 : :
1959 : 5 : set_thread(1);
1960 : 5 : spdk_put_io_channel(ch1);
1961 : 5 : CU_ASSERT(ch_count == 2);
1962 : 5 : set_thread(2);
1963 : 5 : spdk_put_io_channel(ch2);
1964 : 5 : CU_ASSERT(ch_count == 2);
1965 : 5 : poll_threads();
1966 : 5 : CU_ASSERT(ch_count == 0);
1967 : :
1968 : 5 : spdk_io_device_unregister(&ch_count, NULL);
1969 : 5 : poll_threads();
1970 : :
1971 : 5 : free_threads();
1972 : 5 : }
1973 : :
1974 : : static void
1975 : 5 : for_each_thread_and_thread_exit_race(void)
1976 : : {
1977 : : struct spdk_thread *thread0;
1978 : 5 : int count = 0;
1979 : : int i;
1980 : :
1981 : 5 : allocate_threads(3);
1982 : 5 : set_thread(0);
1983 : 5 : thread0 = spdk_get_thread();
1984 : :
1985 : : /* Even if thread 0 starts exiting, spdk_for_each_thread() should complete normally
1986 : : * and then thread 0 should be moved to EXITED.
1987 : : */
1988 : :
1989 : 5 : spdk_for_each_thread(for_each_cb, &count, for_each_cb);
1990 : 5 : CU_ASSERT(thread0->for_each_count == 1);
1991 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_RUNNING);
1992 : :
1993 : 5 : spdk_thread_exit(thread0);
1994 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITING);
1995 : :
1996 : : /* We have not polled thread 0 yet, so count should be 0 */
1997 : 5 : CU_ASSERT(count == 0);
1998 : :
1999 : : /* Poll each thread to verify the message is passed to each */
2000 [ + + ]: 20 : for (i = 0; i < 3; i++) {
2001 : 15 : poll_thread(i);
2002 : 15 : CU_ASSERT(count == (i + 1));
2003 : : }
2004 : :
2005 : : /*
2006 : : * After each thread is called, the completion calls it
2007 : : * one more time.
2008 : : */
2009 : 5 : poll_thread(0);
2010 : 5 : CU_ASSERT(count == 4);
2011 : :
2012 : 5 : CU_ASSERT(thread0->for_each_count == 0);
2013 : 5 : CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITED);
2014 : :
2015 : 5 : free_threads();
2016 : 5 : }
2017 : :
2018 : : int
2019 : 5 : main(int argc, char **argv)
2020 : : {
2021 : 5 : CU_pSuite suite = NULL;
2022 : : unsigned int num_failures;
2023 : :
2024 : 5 : CU_initialize_registry();
2025 : :
2026 : 5 : suite = CU_add_suite("io_channel", NULL, NULL);
2027 : :
2028 : 5 : CU_ADD_TEST(suite, thread_alloc);
2029 : 5 : CU_ADD_TEST(suite, thread_send_msg);
2030 : 5 : CU_ADD_TEST(suite, thread_poller);
2031 : 5 : CU_ADD_TEST(suite, poller_pause);
2032 : 5 : CU_ADD_TEST(suite, thread_for_each);
2033 : 5 : CU_ADD_TEST(suite, for_each_channel_remove);
2034 : 5 : CU_ADD_TEST(suite, for_each_channel_unreg);
2035 : 5 : CU_ADD_TEST(suite, thread_name);
2036 : 5 : CU_ADD_TEST(suite, channel);
2037 : 5 : CU_ADD_TEST(suite, channel_destroy_races);
2038 : 5 : CU_ADD_TEST(suite, thread_exit_test);
2039 : 5 : CU_ADD_TEST(suite, thread_update_stats_test);
2040 : 5 : CU_ADD_TEST(suite, nested_channel);
2041 : 5 : CU_ADD_TEST(suite, device_unregister_and_thread_exit_race);
2042 : 5 : CU_ADD_TEST(suite, cache_closest_timed_poller);
2043 : 5 : CU_ADD_TEST(suite, multi_timed_pollers_have_same_expiration);
2044 : 5 : CU_ADD_TEST(suite, io_device_lookup);
2045 : 5 : CU_ADD_TEST(suite, spdk_spin);
2046 : 5 : CU_ADD_TEST(suite, for_each_channel_and_thread_exit_race);
2047 : 5 : CU_ADD_TEST(suite, for_each_thread_and_thread_exit_race);
2048 : :
2049 : 5 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
2050 : 5 : CU_cleanup_registry();
2051 : 5 : return num_failures;
2052 : : }
|