1 /*
2 * Copyright (c) 2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9
10 #define TEST_WORK_TIMEOUT_MS 100
11 #define TEST_WORK_DURATION_MS (TEST_WORK_TIMEOUT_MS / 2)
12 #define TEST_WORK_DELAY K_MSEC(TEST_WORK_DURATION_MS * 6)
13 #define TEST_WORK_BLOCKING_DELAY K_MSEC(TEST_WORK_TIMEOUT_MS * 2)
14
15 static struct k_work_q test_workq;
16 static K_KERNEL_STACK_DEFINE(test_workq_stack, CONFIG_MAIN_STACK_SIZE);
17
test_work_handler(struct k_work * work)18 static void test_work_handler(struct k_work *work)
19 {
20 k_msleep(TEST_WORK_DURATION_MS);
21 }
22
23 static K_WORK_DEFINE(test_work0, test_work_handler);
24 static K_WORK_DEFINE(test_work1, test_work_handler);
25 static K_WORK_DEFINE(test_work2, test_work_handler);
26 static K_WORK_DEFINE(test_work3, test_work_handler);
27
test_work_handler_blocking(struct k_work * work)28 static void test_work_handler_blocking(struct k_work *work)
29 {
30 k_sleep(K_FOREVER);
31 }
32
33 static K_WORK_DEFINE(test_work_blocking, test_work_handler_blocking);
34
test_setup(void)35 static void *test_setup(void)
36 {
37 const struct k_work_queue_config config = {
38 .name = "sysworkq",
39 .no_yield = false,
40 .essential = false,
41 .work_timeout_ms = TEST_WORK_TIMEOUT_MS,
42 };
43
44 k_work_queue_start(&test_workq,
45 test_workq_stack,
46 K_KERNEL_STACK_SIZEOF(test_workq_stack),
47 0,
48 &config);
49
50 return NULL;
51 }
52
53 ZTEST_SUITE(workqueue_work_timeout, NULL, test_setup, NULL, NULL, NULL);
54
ZTEST(workqueue_work_timeout,test_work)55 ZTEST(workqueue_work_timeout, test_work)
56 {
57 int ret;
58
59 /* Submit multiple items which take less time than TEST_WORK_TIMEOUT_MS each */
60 zassert_equal(k_work_submit_to_queue(&test_workq, &test_work0), 1);
61 zassert_equal(k_work_submit_to_queue(&test_workq, &test_work1), 1);
62 zassert_equal(k_work_submit_to_queue(&test_workq, &test_work2), 1);
63 zassert_equal(k_work_submit_to_queue(&test_workq, &test_work3), 1);
64
65 /*
66 * Submitted items takes longer than TEST_WORK_TIMEOUT_MS, but each item takes
67 * less time than TEST_WORK_DELAY so workqueue thread will not be aborted.
68 */
69 zassert_equal(k_thread_join(&test_workq.thread, TEST_WORK_DELAY), -EAGAIN);
70
71 /* Submit single item which takes longer than TEST_WORK_TIMEOUT_MS */
72 zassert_equal(k_work_submit_to_queue(&test_workq, &test_work_blocking), 1);
73
74 /*
75 * Submitted item shall cause the work to time out and the workqueue thread be
76 * aborted if CONFIG_WORKQUEUE_WORK_TIMEOUT is enabled.
77 */
78 ret = k_thread_join(&test_workq.thread, TEST_WORK_BLOCKING_DELAY);
79 if (IS_ENABLED(CONFIG_WORKQUEUE_WORK_TIMEOUT)) {
80 zassert_equal(ret, 0);
81 } else {
82 zassert_equal(ret, -EAGAIN);
83 }
84 }
85