1 /*
2 * Copyright (c) 2019 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/ztest.h>
7 #include <zephyr/kernel.h>
8
9 #include "tests_thread_apis.h"
10
11 /* Very simple (and limited) test of the SMP cpu mask API. Runs on
12 * just one CPU. Creates a thread, sets the CPU mask, starts it,
13 * checks if it ran (or didn't run) as expected.
14 */
15
16 struct k_thread child_thread;
17
18 bool child_has_run;
19
child_fn(void * a,void * b,void * c)20 void child_fn(void *a, void *b, void *c)
21 {
22 child_has_run = true;
23 }
24
25
26 /**
27 * @brief Test the CPU mask APIs for thread lifecycle management
28 *
29 * This test verifies the behavior of the CPU mask APIs in the Zephyr kernel
30 * for thread lifecycle management. It ensures that the APIs behave as expected
31 * when operating on both running and non-running threads.
32 *
33 * @note This test is only executed if `CONFIG_SCHED_CPU_MASK` is enabled.
34 * Otherwise, the test is skipped.
35 *
36 * @ingroup kernel_thread_tests
37 */
ZTEST(threads_lifecycle_1cpu,test_threads_cpu_mask)38 ZTEST(threads_lifecycle_1cpu, test_threads_cpu_mask)
39 {
40 #ifdef CONFIG_SCHED_CPU_MASK
41 k_tid_t thread;
42 int ret, pass, prio;
43
44 /* Shouldn't be able to operate on a running thread */
45 ret = k_thread_cpu_mask_clear(k_current_get());
46 zassert_true(ret == -EINVAL, "");
47
48 ret = k_thread_cpu_mask_enable_all(k_current_get());
49 zassert_true(ret == -EINVAL, "");
50
51 ret = k_thread_cpu_mask_enable(k_current_get(), 0);
52 zassert_true(ret == -EINVAL, "");
53
54 ret = k_thread_cpu_mask_disable(k_current_get(), 0);
55 zassert_true(ret == -EINVAL, "");
56
57 ret = k_thread_cpu_pin(k_current_get(), 0);
58 zassert_true(ret == -EINVAL, "");
59
60 for (pass = 0; pass < 4; pass++) {
61 if (IS_ENABLED(CONFIG_SCHED_CPU_MASK_PIN_ONLY) && pass == 1) {
62 /* Pass 1 enables more than one CPU in the
63 * mask, which is illegal when PIN_ONLY
64 */
65 continue;
66 }
67
68 child_has_run = false;
69
70 /* Create a thread at a higher priority, don't start
71 * it yet.
72 */
73 prio = k_thread_priority_get(k_current_get());
74 zassert_true(prio > K_HIGHEST_APPLICATION_THREAD_PRIO, "");
75 thread = k_thread_create(&child_thread,
76 tstack, tstack_size,
77 child_fn, NULL, NULL, NULL,
78 K_HIGHEST_APPLICATION_THREAD_PRIO,
79 0, K_FOREVER);
80
81 /* Set up the CPU mask */
82 if (pass == 0) {
83 ret = k_thread_cpu_mask_clear(thread);
84 zassert_true(ret == 0, "");
85 } else if (pass == 1) {
86 ret = k_thread_cpu_mask_enable_all(thread);
87 zassert_true(ret == 0, "");
88 } else if (pass == 2) {
89 ret = k_thread_cpu_mask_disable(thread, 0);
90 zassert_true(ret == 0, "");
91 } else {
92 ret = k_thread_cpu_mask_enable(thread, 0);
93 zassert_true(ret == 0, "");
94
95 ret = k_thread_cpu_pin(thread, 0);
96 zassert_true(ret == 0, "");
97 }
98
99 /* Start it. If it is runnable, it will do so
100 * immediately when we yield. Check to see if it ran.
101 */
102 zassert_false(child_has_run, "");
103 k_thread_start(thread);
104 k_yield();
105
106 if (pass == 1 || pass == 3) {
107 zassert_true(child_has_run, "");
108 } else {
109 zassert_false(child_has_run, "");
110 }
111
112 k_thread_abort(thread);
113 }
114 #else
115 ztest_test_skip();
116 #endif
117 }
118