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