1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdbool.h>
8
9 /* This test covers deprecated API. Avoid inappropriate diagnostics
10 * about the use of that API.
11 */
12 #include <zephyr/toolchain.h>
13 #undef __deprecated
14 #define __deprecated
15 #undef __DEPRECATED_MACRO
16 #define __DEPRECATED_MACRO
17
18 #include <zephyr/kernel.h>
19 #include <zephyr/ztest.h>
20 #include <zephyr/tc_util.h>
21 #include <zephyr/sys/util.h>
22
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(test);
25
26 #define NUM_TEST_ITEMS 6
27
28 /* Each work item takes 100ms by default. */
29 #define WORK_ITEM_WAIT (CONFIG_TEST_WORK_ITEM_WAIT_MS)
30
31 /* In fact, each work item could take up to this value */
32 #define WORK_ITEM_WAIT_ALIGNED \
33 k_ticks_to_ms_floor64(k_ms_to_ticks_ceil32(WORK_ITEM_WAIT) + _TICK_ALIGN)
34
35 /*
36 * Wait 50ms between work submissions, to ensure co-op and prempt
37 * preempt thread submit alternatively.
38 */
39 #define SUBMIT_WAIT (CONFIG_TEST_SUBMIT_WAIT_MS)
40
41 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
42
43 /* How long to wait for the full test suite to complete. Allow for a
44 * little slop
45 */
46 #define CHECK_WAIT ((NUM_TEST_ITEMS + 1) * WORK_ITEM_WAIT_ALIGNED)
47
48 struct delayed_test_item {
49 int key;
50 struct k_work_delayable work;
51 };
52
53 struct triggered_test_item {
54 int key;
55 struct k_work_poll work;
56 struct k_poll_signal signal;
57 struct k_poll_event event;
58 };
59
60
61 static K_THREAD_STACK_DEFINE(co_op_stack, STACK_SIZE);
62 static struct k_thread co_op_data;
63
64 static struct delayed_test_item delayed_tests[NUM_TEST_ITEMS];
65 static struct triggered_test_item triggered_tests[NUM_TEST_ITEMS];
66
67 static int results[NUM_TEST_ITEMS];
68 static int num_results;
69 static int expected_poll_result;
70
71 #define MSG_PROVIDER_THREAD_STACK_SIZE 0x400U
72 #define MSG_CONSUMER_WORKQ_STACK_SIZE 0x400U
73
74 #define MSG_PROVIDER_THREAD_PRIO K_PRIO_PREEMPT(8)
75 #define MSG_CONSUMER_WORKQ_PRIO K_PRIO_COOP(7)
76 #define MSG_SIZE 16U
77
78 static K_THREAD_STACK_DEFINE(provider_thread_stack, MSG_PROVIDER_THREAD_STACK_SIZE);
79 static K_THREAD_STACK_DEFINE(consumer_workq_stack, MSG_CONSUMER_WORKQ_STACK_SIZE);
80
81 struct triggered_from_msgq_test_item {
82 k_tid_t tid;
83 struct k_thread msg_provider_thread;
84 struct k_work_q msg_consumer_workq;
85 struct k_work_poll work;
86 char msgq_buf[1][MSG_SIZE];
87 struct k_msgq msgq;
88 struct k_poll_event event;
89 };
90
91 static struct triggered_from_msgq_test_item triggered_from_msgq_test;
92
work_handler(struct k_work * work)93 static void work_handler(struct k_work *work)
94 {
95 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
96 struct delayed_test_item *ti =
97 CONTAINER_OF(dwork, struct delayed_test_item, work);
98
99 LOG_DBG(" - Running test item %d", ti->key);
100 k_msleep(WORK_ITEM_WAIT);
101
102 results[num_results++] = ti->key;
103 }
104
105 /**
106 * @ingroup kernel_workqueue_tests
107 * @see k_work_init()
108 */
delayed_test_items_init(void)109 static void delayed_test_items_init(void)
110 {
111 int i;
112
113 for (i = 0; i < NUM_TEST_ITEMS; i++) {
114 delayed_tests[i].key = i + 1;
115 k_work_init_delayable(&delayed_tests[i].work, work_handler);
116 }
117 }
118
reset_results(void)119 static void reset_results(void)
120 {
121 int i;
122
123 for (i = 0; i < NUM_TEST_ITEMS; i++) {
124 results[i] = 0;
125 }
126
127 num_results = 0;
128 }
129
coop_work_main(void * p1,void * p2,void * p3)130 static void coop_work_main(void *p1, void *p2, void *p3)
131 {
132 ARG_UNUSED(p1);
133 ARG_UNUSED(p2);
134 ARG_UNUSED(p3);
135
136 int i;
137
138 /* Let the preempt thread submit the first work item. */
139 k_msleep(SUBMIT_WAIT / 2);
140
141 for (i = 1; i < NUM_TEST_ITEMS; i += 2) {
142 LOG_DBG(" - Submitting work %d from coop thread", i + 1);
143 k_work_schedule(&delayed_tests[i].work, K_NO_WAIT);
144 k_msleep(SUBMIT_WAIT);
145 }
146 }
147
148 /**
149 * @ingroup kernel_workqueue_tests
150 * @see k_work_submit()
151 */
delayed_test_items_submit(void)152 static void delayed_test_items_submit(void)
153 {
154 int i;
155
156 k_thread_create(&co_op_data, co_op_stack, STACK_SIZE,
157 coop_work_main,
158 NULL, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT);
159
160 for (i = 0; i < NUM_TEST_ITEMS; i += 2) {
161 LOG_DBG(" - Submitting work %d from preempt thread", i + 1);
162 k_work_schedule(&delayed_tests[i].work, K_NO_WAIT);
163 k_msleep(SUBMIT_WAIT);
164 }
165 }
166
check_results(int num_tests)167 static void check_results(int num_tests)
168 {
169 int i;
170
171 zassert_equal(num_results, num_tests,
172 "*** work items finished: %d (expected: %d)\n",
173 num_results, num_tests);
174
175 for (i = 0; i < num_tests; i++) {
176 zassert_equal(results[i], i + 1,
177 "*** got result %d in position %d"
178 " (expected %d)\n",
179 results[i], i, i + 1);
180 }
181
182 }
183
184 /**
185 * @brief Test work queue items submission sequence
186 *
187 * @ingroup kernel_workqueue_tests
188 *
189 * @see k_work_init(), k_work_submit()
190 */
test_sequence(void)191 static void test_sequence(void)
192 {
193 LOG_DBG(" - Initializing test items");
194 delayed_test_items_init();
195
196 LOG_DBG(" - Submitting test items");
197 delayed_test_items_submit();
198
199 LOG_DBG(" - Waiting for work to finish");
200 k_msleep(CHECK_WAIT);
201
202 check_results(NUM_TEST_ITEMS);
203 reset_results();
204 }
205
206
207
resubmit_work_handler(struct k_work * work)208 static void resubmit_work_handler(struct k_work *work)
209 {
210 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
211 struct delayed_test_item *ti =
212 CONTAINER_OF(dwork, struct delayed_test_item, work);
213
214 k_msleep(WORK_ITEM_WAIT);
215
216 results[num_results++] = ti->key;
217
218 if (ti->key < NUM_TEST_ITEMS) {
219 ti->key++;
220 LOG_DBG(" - Resubmitting work");
221 k_work_submit(work);
222 }
223 }
224 /**
225 * @brief Test work queue item resubmission
226 *
227 * @ingroup kernel_workqueue_tests
228 *
229 * @see k_work_submit()
230 */
ZTEST(workqueue_triggered,test_resubmit)231 ZTEST(workqueue_triggered, test_resubmit)
232 {
233 LOG_DBG("Starting resubmit test");
234
235 delayed_tests[0].key = 1;
236 k_work_init_delayable(&delayed_tests[0].work, resubmit_work_handler);
237
238 LOG_DBG(" - Submitting work");
239 k_work_schedule(&delayed_tests[0].work, K_NO_WAIT);
240
241 LOG_DBG(" - Waiting for work to finish");
242 k_msleep(CHECK_WAIT);
243
244 LOG_DBG(" - Checking results");
245 check_results(NUM_TEST_ITEMS);
246 reset_results();
247 }
248
delayed_work_handler(struct k_work * work)249 static void delayed_work_handler(struct k_work *work)
250 {
251 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
252 struct delayed_test_item *ti =
253 CONTAINER_OF(dwork, struct delayed_test_item, work);
254
255 LOG_DBG(" - Running delayed test item %d", ti->key);
256
257 results[num_results++] = ti->key;
258 }
259
260 /**
261 * @brief Test delayed work queue init
262 *
263 * @ingroup kernel_workqueue_tests
264 *
265 * @see k_work_init_delayable()
266 */
test_delayed_init(void)267 static void test_delayed_init(void)
268 {
269 int i;
270
271 for (i = 0; i < NUM_TEST_ITEMS; i++) {
272 delayed_tests[i].key = i + 1;
273 k_work_init_delayable(&delayed_tests[i].work,
274 delayed_work_handler);
275 }
276 }
277
coop_delayed_work_main(void * p1,void * p2,void * p3)278 static void coop_delayed_work_main(void *p1, void *p2, void *p3)
279 {
280 ARG_UNUSED(p1);
281 ARG_UNUSED(p2);
282 ARG_UNUSED(p3);
283
284 int i;
285
286 /* Let the preempt thread submit the first work item. */
287 k_msleep(SUBMIT_WAIT / 2);
288
289 for (i = 1; i < NUM_TEST_ITEMS; i += 2) {
290 LOG_DBG(" - Submitting delayed work %d from"
291 " coop thread", i + 1);
292 k_work_schedule(&delayed_tests[i].work,
293 K_MSEC((i + 1) * WORK_ITEM_WAIT));
294 }
295 }
296
297 /**
298 * @brief Test delayed workqueue submit
299 *
300 * @ingroup kernel_workqueue_tests
301 *
302 * @see k_work_init_delayable(), k_work_schedule()
303 */
test_delayed_submit(void)304 static void test_delayed_submit(void)
305 {
306 int i;
307
308 k_thread_create(&co_op_data, co_op_stack, STACK_SIZE,
309 coop_delayed_work_main,
310 NULL, NULL, NULL, K_PRIO_COOP(10), 0, K_NO_WAIT);
311
312 for (i = 0; i < NUM_TEST_ITEMS; i += 2) {
313 LOG_DBG(" - Submitting delayed work %d from"
314 " preempt thread", i + 1);
315 zassert_true(k_work_reschedule(&delayed_tests[i].work,
316 K_MSEC((i + 1) * WORK_ITEM_WAIT)) >= 0, NULL);
317 }
318
319 }
320
coop_delayed_work_cancel_main(void * p1,void * p2,void * p3)321 static void coop_delayed_work_cancel_main(void *p1, void *p2, void *p3)
322 {
323 ARG_UNUSED(p1);
324 ARG_UNUSED(p2);
325 ARG_UNUSED(p3);
326
327 k_work_schedule(&delayed_tests[1].work, K_MSEC(WORK_ITEM_WAIT));
328
329 LOG_DBG(" - Cancel delayed work from coop thread");
330 k_work_cancel_delayable(&delayed_tests[1].work);
331 }
332
333 /**
334 * @brief Test work queue delayed cancel
335 *
336 * @ingroup kernel_workqueue_tests
337 *
338 * @see k_work_delayable_init(), k_work_schedule(),
339 * k_work_cancel_delayable()
340 */
ZTEST(workqueue_delayed,test_delayed_cancel)341 ZTEST(workqueue_delayed, test_delayed_cancel)
342 {
343 LOG_DBG("Starting delayed cancel test");
344
345 k_work_schedule(&delayed_tests[0].work, K_MSEC(WORK_ITEM_WAIT));
346
347 LOG_DBG(" - Cancel delayed work from preempt thread");
348 k_work_cancel_delayable(&delayed_tests[0].work);
349
350 k_thread_create(&co_op_data, co_op_stack, STACK_SIZE,
351 coop_delayed_work_cancel_main,
352 NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT);
353
354 LOG_DBG(" - Waiting for work to finish");
355 k_msleep(WORK_ITEM_WAIT_ALIGNED);
356
357 LOG_DBG(" - Checking results");
358 check_results(0);
359 reset_results();
360 }
361
ZTEST(workqueue_delayed,test_delayed_pending)362 ZTEST(workqueue_delayed, test_delayed_pending)
363 {
364 LOG_DBG("Starting delayed pending test");
365
366 k_work_init_delayable(&delayed_tests[0].work, delayed_work_handler);
367
368 zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work));
369
370 LOG_DBG(" - Check pending delayed work when in workqueue");
371 k_work_schedule(&delayed_tests[0].work, K_NO_WAIT);
372 zassert_true(k_work_delayable_is_pending(&delayed_tests[0].work));
373
374 k_msleep(1);
375 zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work));
376
377 LOG_DBG(" - Checking results");
378 check_results(1);
379 reset_results();
380
381 LOG_DBG(" - Check pending delayed work with timeout");
382 k_work_schedule(&delayed_tests[0].work, K_MSEC(WORK_ITEM_WAIT));
383 zassert_true(k_work_delayable_is_pending(&delayed_tests[0].work));
384
385 k_msleep(WORK_ITEM_WAIT_ALIGNED);
386 zassert_false(k_work_delayable_is_pending(&delayed_tests[0].work));
387
388 LOG_DBG(" - Checking results");
389 check_results(1);
390 reset_results();
391 }
392
393 /**
394 * @brief Test delayed work items
395 *
396 * @ingroup kernel_workqueue_tests
397 *
398 * @see k_work_init_delayable(), k_work_schedule()
399 */
ZTEST(workqueue_delayed,test_delayed)400 ZTEST(workqueue_delayed, test_delayed)
401 {
402 LOG_DBG("Starting delayed test");
403
404 LOG_DBG(" - Initializing delayed test items");
405 test_delayed_init();
406
407 LOG_DBG(" - Submitting delayed test items");
408 test_delayed_submit();
409
410 LOG_DBG(" - Waiting for delayed work to finish");
411 k_msleep(CHECK_WAIT);
412
413 LOG_DBG(" - Checking results");
414 check_results(NUM_TEST_ITEMS);
415 reset_results();
416 }
417
triggered_work_handler(struct k_work * work)418 static void triggered_work_handler(struct k_work *work)
419 {
420 struct k_work_poll *pwork = CONTAINER_OF(work, struct k_work_poll, work);
421 struct triggered_test_item *ti =
422 CONTAINER_OF(pwork, struct triggered_test_item, work);
423
424 LOG_DBG(" - Running triggered test item %d", ti->key);
425
426 zassert_equal(ti->work.poll_result, expected_poll_result,
427 "res %d expect %d", ti->work.poll_result, expected_poll_result);
428
429 results[num_results++] = ti->key;
430 }
431
432 /**
433 * @brief Test triggered work queue init
434 *
435 * @ingroup kernel_workqueue_tests
436 *
437 * @see k_work_poll_init()
438 */
test_triggered_init(void)439 static void test_triggered_init(void)
440 {
441 int i;
442
443 for (i = 0; i < NUM_TEST_ITEMS; i++) {
444 triggered_tests[i].key = i + 1;
445 k_work_poll_init(&triggered_tests[i].work,
446 triggered_work_handler);
447
448 k_poll_signal_init(&triggered_tests[i].signal);
449 k_poll_event_init(&triggered_tests[i].event,
450 K_POLL_TYPE_SIGNAL,
451 K_POLL_MODE_NOTIFY_ONLY,
452 &triggered_tests[i].signal);
453 }
454 }
455
456 /**
457 * @brief Test triggered workqueue submit
458 *
459 * @ingroup kernel_workqueue_tests
460 *
461 * @see k_work_poll_init(), k_work_poll_submit()
462 */
test_triggered_submit(k_timeout_t timeout)463 static void test_triggered_submit(k_timeout_t timeout)
464 {
465 int i;
466
467 for (i = 0; i < NUM_TEST_ITEMS; i++) {
468 LOG_DBG(" - Submitting triggered work %d", i + 1);
469 zassert_true(k_work_poll_submit(&triggered_tests[i].work,
470 &triggered_tests[i].event,
471 1, timeout) == 0, NULL);
472 }
473 }
474
475 /**
476 * @brief Trigger triggered workqueue execution
477 *
478 * @ingroup kernel_workqueue_tests
479 */
test_triggered_trigger(void)480 static void test_triggered_trigger(void)
481 {
482 int i;
483
484 for (i = 0; i < NUM_TEST_ITEMS; i++) {
485 LOG_DBG(" - Triggering work %d", i + 1);
486 zassert_true(k_poll_signal_raise(&triggered_tests[i].signal,
487 1) == 0, NULL);
488 }
489 }
490
491 /**
492 * @brief Test triggered work items
493 *
494 * @ingroup kernel_workqueue_tests
495 *
496 * @see k_work_poll_init(), k_work_poll_submit()
497 */
ZTEST(workqueue_triggered,test_triggered)498 ZTEST(workqueue_triggered, test_triggered)
499 {
500 LOG_DBG("Starting triggered test");
501
502 /* As work items are triggered, they should indicate an event. */
503 expected_poll_result = 0;
504
505 LOG_DBG(" - Initializing triggered test items");
506 test_triggered_init();
507
508 LOG_DBG(" - Submitting triggered test items");
509 test_triggered_submit(K_FOREVER);
510
511 LOG_DBG(" - Triggering test items execution");
512 test_triggered_trigger();
513
514 /* Items should be executed when we will be sleeping. */
515 k_msleep(WORK_ITEM_WAIT);
516
517 LOG_DBG(" - Checking results");
518 check_results(NUM_TEST_ITEMS);
519 reset_results();
520 }
521
522 /**
523 * @brief Test already triggered work items
524 *
525 * @ingroup kernel_workqueue_tests
526 *
527 * @see k_work_poll_init(), k_work_poll_submit()
528 */
ZTEST(workqueue_triggered,test_already_triggered)529 ZTEST(workqueue_triggered, test_already_triggered)
530 {
531 LOG_DBG("Starting triggered test");
532
533 /* As work items are triggered, they should indicate an event. */
534 expected_poll_result = 0;
535
536 LOG_DBG(" - Initializing triggered test items");
537 test_triggered_init();
538
539 LOG_DBG(" - Triggering test items execution");
540 test_triggered_trigger();
541
542 LOG_DBG(" - Submitting triggered test items");
543 test_triggered_submit(K_FOREVER);
544
545 /* Items should be executed when we will be sleeping. */
546 k_msleep(WORK_ITEM_WAIT);
547
548 LOG_DBG(" - Checking results");
549 check_results(NUM_TEST_ITEMS);
550 reset_results();
551 }
552
triggered_resubmit_work_handler(struct k_work * work)553 static void triggered_resubmit_work_handler(struct k_work *work)
554 {
555 struct k_work_poll *pwork = CONTAINER_OF(work, struct k_work_poll, work);
556 struct triggered_test_item *ti =
557 CONTAINER_OF(pwork, struct triggered_test_item, work);
558
559 results[num_results++] = ti->key;
560
561 if (ti->key < NUM_TEST_ITEMS) {
562 ti->key++;
563 LOG_DBG(" - Resubmitting triggered work");
564
565 k_poll_signal_reset(&triggered_tests[0].signal);
566 zassert_true(k_work_poll_submit(&triggered_tests[0].work,
567 &triggered_tests[0].event,
568 1, K_FOREVER) == 0, NULL);
569 }
570 }
571
572 /**
573 * @brief Test resubmission of triggered work queue item
574 *
575 * @ingroup kernel_workqueue_tests
576 *
577 * @see k_work_poll_init(), k_work_poll_submit()
578 */
ZTEST(workqueue_triggered,test_triggered_resubmit)579 ZTEST(workqueue_triggered, test_triggered_resubmit)
580 {
581 int i;
582
583 LOG_DBG("Starting triggered resubmit test");
584
585 /* As work items are triggered, they should indicate an event. */
586 expected_poll_result = 0;
587
588 triggered_tests[0].key = 1;
589 k_work_poll_init(&triggered_tests[0].work,
590 triggered_resubmit_work_handler);
591
592 k_poll_signal_init(&triggered_tests[0].signal);
593 k_poll_event_init(&triggered_tests[0].event,
594 K_POLL_TYPE_SIGNAL,
595 K_POLL_MODE_NOTIFY_ONLY,
596 &triggered_tests[0].signal);
597
598 LOG_DBG(" - Submitting triggered work");
599 zassert_true(k_work_poll_submit(&triggered_tests[0].work,
600 &triggered_tests[0].event,
601 1, K_FOREVER) == 0, NULL);
602
603 for (i = 0; i < NUM_TEST_ITEMS; i++) {
604 LOG_DBG(" - Triggering test item execution (iteration: %d)", i + 1);
605 zassert_true(k_poll_signal_raise(&triggered_tests[0].signal,
606 1) == 0, NULL);
607 k_msleep(WORK_ITEM_WAIT);
608 }
609
610 LOG_DBG(" - Checking results");
611 check_results(NUM_TEST_ITEMS);
612 reset_results();
613 }
614
615 /**
616 * @brief Test triggered work items with K_NO_WAIT timeout
617 *
618 * @ingroup kernel_workqueue_tests
619 *
620 * @see k_work_poll_init(), k_work_poll_submit()
621 */
ZTEST(workqueue_triggered,test_triggered_no_wait)622 ZTEST(workqueue_triggered, test_triggered_no_wait)
623 {
624 LOG_DBG("Starting triggered test");
625
626 /* As work items are triggered, they should indicate an event. */
627 expected_poll_result = 0;
628
629 LOG_DBG(" - Initializing triggered test items");
630 test_triggered_init();
631
632 LOG_DBG(" - Triggering test items execution");
633 test_triggered_trigger();
634
635 LOG_DBG(" - Submitting triggered test items");
636 test_triggered_submit(K_NO_WAIT);
637
638 /* Items should be executed when we will be sleeping. */
639 k_msleep(WORK_ITEM_WAIT);
640
641 LOG_DBG(" - Checking results");
642 check_results(NUM_TEST_ITEMS);
643 reset_results();
644 }
645
646 /**
647 * @brief Test expired triggered work items with K_NO_WAIT timeout
648 *
649 * @ingroup kernel_workqueue_tests
650 *
651 * @see k_work_poll_init(), k_work_poll_submit()
652 */
ZTEST(workqueue_triggered,test_triggered_no_wait_expired)653 ZTEST(workqueue_triggered, test_triggered_no_wait_expired)
654 {
655 LOG_DBG("Starting triggered test");
656
657 /* As work items are not triggered, they should be marked as expired. */
658 expected_poll_result = -EAGAIN;
659
660 LOG_DBG(" - Initializing triggered test items");
661 test_triggered_init();
662
663 LOG_DBG(" - Submitting triggered test items");
664 test_triggered_submit(K_NO_WAIT);
665
666 /* Items should be executed when we will be sleeping. */
667 k_msleep(WORK_ITEM_WAIT);
668
669 LOG_DBG(" - Checking results");
670 check_results(NUM_TEST_ITEMS);
671 reset_results();
672 }
673
674 /**
675 * @brief Test triggered work items with arbitrary timeout
676 *
677 * @ingroup kernel_workqueue_tests
678 *
679 * @see k_work_poll_init(), k_work_poll_submit()
680 */
ZTEST(workqueue_triggered,test_triggered_wait)681 ZTEST(workqueue_triggered, test_triggered_wait)
682 {
683 LOG_DBG("Starting triggered test");
684
685 /* As work items are triggered, they should indicate an event. */
686 expected_poll_result = 0;
687
688 LOG_DBG(" - Initializing triggered test items");
689 test_triggered_init();
690
691 LOG_DBG(" - Triggering test items execution");
692 test_triggered_trigger();
693
694 LOG_DBG(" - Submitting triggered test items");
695 test_triggered_submit(K_MSEC(2 * SUBMIT_WAIT));
696
697 /* Items should be executed when we will be sleeping. */
698 k_msleep(SUBMIT_WAIT);
699
700 LOG_DBG(" - Checking results");
701 check_results(NUM_TEST_ITEMS);
702 reset_results();
703 }
704
705 /**
706 * @brief Test expired triggered work items with arbitrary timeout
707 *
708 * @ingroup kernel_workqueue_tests
709 *
710 * @see k_work_poll_init(), k_work_poll_submit()
711 */
ZTEST(workqueue_triggered,test_triggered_wait_expired)712 ZTEST(workqueue_triggered, test_triggered_wait_expired)
713 {
714 LOG_DBG("Starting triggered test");
715
716 /* As work items are not triggered, they should time out. */
717 expected_poll_result = -EAGAIN;
718
719 LOG_DBG(" - Initializing triggered test items");
720 test_triggered_init();
721
722 LOG_DBG(" - Submitting triggered test items");
723 test_triggered_submit(K_MSEC(2 * SUBMIT_WAIT));
724
725 /* Items should not be executed when we will be sleeping here. */
726 k_msleep(SUBMIT_WAIT);
727 LOG_DBG(" - Checking results (before timeout)");
728 check_results(0);
729
730 /* Items should be executed when we will be sleeping here. */
731 k_msleep(SUBMIT_WAIT * 2);
732 LOG_DBG(" - Checking results (after timeout)");
733 check_results(NUM_TEST_ITEMS);
734
735 reset_results();
736 }
737
738
msg_provider_thread(void * p1,void * p2,void * p3)739 static void msg_provider_thread(void *p1, void *p2, void *p3)
740 {
741 ARG_UNUSED(p1);
742 ARG_UNUSED(p2);
743 ARG_UNUSED(p3);
744
745 char msg[MSG_SIZE] = { 0 };
746
747 k_msgq_put(&triggered_from_msgq_test.msgq, &msg, K_NO_WAIT);
748 }
749
triggered_from_msgq_work_handler(struct k_work * work)750 static void triggered_from_msgq_work_handler(struct k_work *work)
751 {
752 char msg[MSG_SIZE];
753
754 k_msgq_get(&triggered_from_msgq_test.msgq, &msg, K_NO_WAIT);
755 }
756
test_triggered_from_msgq_init(void)757 static void test_triggered_from_msgq_init(void)
758 {
759 struct triggered_from_msgq_test_item *const ctx = &triggered_from_msgq_test;
760
761 ctx->tid = k_thread_create(&ctx->msg_provider_thread,
762 provider_thread_stack,
763 MSG_PROVIDER_THREAD_STACK_SIZE,
764 msg_provider_thread,
765 NULL, NULL, NULL,
766 MSG_PROVIDER_THREAD_PRIO, 0, K_FOREVER);
767 k_work_queue_init(&ctx->msg_consumer_workq);
768 k_msgq_init(&ctx->msgq,
769 (char *)ctx->msgq_buf,
770 MSG_SIZE, 1U);
771 k_work_poll_init(&ctx->work, triggered_from_msgq_work_handler);
772 k_poll_event_init(&ctx->event, K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
773 K_POLL_MODE_NOTIFY_ONLY, &ctx->msgq);
774
775 k_work_queue_start(&ctx->msg_consumer_workq, consumer_workq_stack,
776 MSG_CONSUMER_WORKQ_STACK_SIZE, MSG_CONSUMER_WORKQ_PRIO,
777 NULL);
778 k_work_poll_submit_to_queue(&ctx->msg_consumer_workq, &ctx->work,
779 &ctx->event, 1U, K_FOREVER);
780 }
781
test_triggered_from_msgq_start(void)782 static void test_triggered_from_msgq_start(void)
783 {
784 k_thread_start(triggered_from_msgq_test.tid);
785 }
786 /**
787 * @brief Test triggered work item, triggered by a msgq message.
788 *
789 * Regression test for issue #45267:
790 *
791 * When an object availability event triggers a k_work_poll item,
792 * the object lock should not be held anymore during the execution
793 * of the work callback.
794 *
795 * Tested with msgq with K_POLL_TYPE_MSGQ_DATA_AVAILABLE.
796 *
797 * @ingroup kernel_workqueue_tests
798 *
799 * @see k_work_poll_init(), k_work_poll_submit()
800 *
801 */
ZTEST(workqueue_triggered,test_triggered_from_msgq)802 ZTEST(workqueue_triggered, test_triggered_from_msgq)
803 {
804 LOG_DBG("Starting triggered from msgq test");
805
806 LOG_DBG(" - Initializing kernel objects");
807 test_triggered_from_msgq_init();
808
809 LOG_DBG(" - Starting the thread");
810 test_triggered_from_msgq_start();
811
812 reset_results();
813 }
814
815 /**
816 * @brief Test delayed work queue define macro.
817 *
818 * @ingroup kernel_workqueue_tests
819 *
820 * @see K_WORK_DELAYABLE_DEFINE()
821 */
ZTEST(workqueue_triggered,test_delayed_work_define)822 ZTEST(workqueue_triggered, test_delayed_work_define)
823 {
824 struct k_work_delayable initialized_by_function = { 0 };
825
826 K_WORK_DELAYABLE_DEFINE(initialized_by_macro, delayed_work_handler);
827
828 k_work_init_delayable(&initialized_by_function, delayed_work_handler);
829
830 zassert_mem_equal(&initialized_by_function, &initialized_by_macro,
831 sizeof(struct k_work_delayable), NULL);
832 }
833
834 /**
835 * @brief Verify k_work_poll_cancel()
836 *
837 * @ingroup kernel_workqueue_tests
838 *
839 * @details Cancel a triggered work item repeatedly,
840 * see if it returns expected value.
841 *
842 * @see k_work_poll_cancel()
843 */
ZTEST(workqueue_triggered,test_triggered_cancel)844 ZTEST(workqueue_triggered, test_triggered_cancel)
845 {
846 int ret;
847
848 LOG_DBG("Starting triggered test");
849
850 /* As work items are triggered, they should indicate an event. */
851 expected_poll_result = 0;
852
853 LOG_DBG(" - Initializing triggered test items");
854 test_triggered_init();
855
856 test_triggered_submit(K_FOREVER);
857
858 ret = k_work_poll_cancel(&triggered_tests[0].work);
859 zassert_true(ret == 0, "triggered cancel failed");
860
861 ret = k_work_poll_cancel(&triggered_tests[0].work);
862 zassert_true(ret == -EINVAL, "triggered cancel failed");
863
864 ret = k_work_poll_cancel(NULL);
865 zassert_true(ret == -EINVAL, "triggered cancel failed");
866 }
867
868 /*test case main entry*/
workq_setup(void)869 static void *workq_setup(void)
870 {
871 k_thread_priority_set(k_current_get(), 0);
872 test_sequence();
873
874 return NULL;
875 }
876
877
878 ZTEST_SUITE(workqueue_delayed, NULL, workq_setup, ztest_simple_1cpu_before,
879 ztest_simple_1cpu_after, NULL);
880 ZTEST_SUITE(workqueue_triggered, NULL, workq_setup, ztest_simple_1cpu_before,
881 ztest_simple_1cpu_after, NULL);
882