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