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