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 
ZTEST(threads_lifecycle_1cpu,test_threads_cpu_mask)25 ZTEST(threads_lifecycle_1cpu, test_threads_cpu_mask)
26 {
27 #ifdef CONFIG_SCHED_CPU_MASK
28 	k_tid_t thread;
29 	int ret, pass, prio;
30 
31 	/* Shouldn't be able to operate on a running thread */
32 	ret = k_thread_cpu_mask_clear(k_current_get());
33 	zassert_true(ret == -EINVAL, "");
34 
35 	ret = k_thread_cpu_mask_enable_all(k_current_get());
36 	zassert_true(ret == -EINVAL, "");
37 
38 	ret = k_thread_cpu_mask_enable(k_current_get(), 0);
39 	zassert_true(ret == -EINVAL, "");
40 
41 	ret = k_thread_cpu_mask_disable(k_current_get(), 0);
42 	zassert_true(ret == -EINVAL, "");
43 
44 	ret = k_thread_cpu_pin(k_current_get(), 0);
45 	zassert_true(ret == -EINVAL, "");
46 
47 	for (pass = 0; pass < 4; pass++) {
48 		if (IS_ENABLED(CONFIG_SCHED_CPU_MASK_PIN_ONLY) && pass == 1) {
49 			/* Pass 1 enables more than one CPU in the
50 			 * mask, which is illegal when PIN_ONLY
51 			 */
52 			continue;
53 		}
54 
55 		child_has_run = false;
56 
57 		/* Create a thread at a higher priority, don't start
58 		 * it yet.
59 		 */
60 		prio = k_thread_priority_get(k_current_get());
61 		zassert_true(prio > K_HIGHEST_APPLICATION_THREAD_PRIO, "");
62 		thread = k_thread_create(&child_thread,
63 					 tstack, tstack_size,
64 					 child_fn, NULL, NULL, NULL,
65 					 K_HIGHEST_APPLICATION_THREAD_PRIO,
66 					 0, K_FOREVER);
67 
68 		/* Set up the CPU mask */
69 		if (pass == 0) {
70 			ret = k_thread_cpu_mask_clear(thread);
71 			zassert_true(ret == 0, "");
72 		} else if (pass == 1) {
73 			ret = k_thread_cpu_mask_enable_all(thread);
74 			zassert_true(ret == 0, "");
75 		} else if (pass == 2) {
76 			ret = k_thread_cpu_mask_disable(thread, 0);
77 			zassert_true(ret == 0, "");
78 		} else {
79 			ret = k_thread_cpu_mask_enable(thread, 0);
80 			zassert_true(ret == 0, "");
81 
82 			ret = k_thread_cpu_pin(thread, 0);
83 			zassert_true(ret == 0, "");
84 		}
85 
86 		/* Start it.  If it is runnable, it will do so
87 		 * immediately when we yield.  Check to see if it ran.
88 		 */
89 		zassert_false(child_has_run, "");
90 		k_thread_start(thread);
91 		k_yield();
92 
93 		if (pass == 1 || pass == 3) {
94 			zassert_true(child_has_run, "");
95 		} else {
96 			zassert_false(child_has_run, "");
97 		}
98 
99 		k_thread_abort(thread);
100 	}
101 #else
102 	ztest_test_skip();
103 #endif
104 }
105