1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "test_sched.h"
8 #include <zephyr/ztest.h>
9 #include <zephyr/irq_offload.h>
10 #include <kernel_internal.h>
11 #include <zephyr/ztest_error_hook.h>
12 
13 struct k_thread user_thread;
14 K_SEM_DEFINE(user_sem, 0, 1);
15 
16 ZTEST_BMEM volatile int thread_was_preempt;
17 
18 #define THREAD_TEST_PRIORITY 0
19 
20 K_THREAD_STACK_DEFINE(ustack, STACK_SIZE);
21 
sleepy_thread(void * p1,void * p2,void * p3)22 static void sleepy_thread(void *p1, void *p2, void *p3)
23 {
24 	ARG_UNUSED(p1);
25 	ARG_UNUSED(p2);
26 	ARG_UNUSED(p3);
27 
28 	k_sleep(K_FOREVER);
29 	k_sem_give(&user_sem);
30 }
31 
ZTEST_USER(threads_scheduling,test_user_k_wakeup)32 ZTEST_USER(threads_scheduling, test_user_k_wakeup)
33 {
34 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, sleepy_thread,
35 			NULL, NULL, NULL,
36 			k_thread_priority_get(k_current_get()),
37 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
38 
39 	k_yield(); /* Let thread run and start sleeping forever */
40 	k_wakeup(&user_thread);
41 	k_sem_take(&user_sem, K_FOREVER);
42 	k_thread_abort(tid);
43 }
44 
preempt_test_thread(void * p1,void * p2,void * p3)45 static void preempt_test_thread(void *p1, void *p2, void *p3)
46 {
47 	ARG_UNUSED(p1);
48 	ARG_UNUSED(p2);
49 	ARG_UNUSED(p3);
50 
51 	thread_was_preempt = k_is_preempt_thread();
52 	k_sem_give(&user_sem);
53 }
54 
ZTEST_USER(threads_scheduling,test_user_k_is_preempt)55 ZTEST_USER(threads_scheduling, test_user_k_is_preempt)
56 {
57 	/* thread_was_preempt is volatile, and static analysis doesn't
58 	 * like to see it being tested inside zassert_true, because
59 	 * the read is treated as a "side effect" of an assertion
60 	 * (e.g. a read is significant for things like volatile MMIO
61 	 * addresses, and assertions may or may not be compiled, even
62 	 * though here in a test they always will be and in any case
63 	 * the value is a static variable above marked volatile for
64 	 * threadsafety).  Read it into a local variable first to
65 	 * evade the warning.
66 	 */
67 	int twp;
68 
69 	k_tid_t tid = k_thread_create(&user_thread, ustack,
70 			STACK_SIZE, preempt_test_thread, NULL, NULL, NULL,
71 			k_thread_priority_get(k_current_get()),
72 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
73 
74 	k_sem_take(&user_sem, K_FOREVER);
75 
76 	twp = thread_was_preempt;
77 	zassert_false(twp, "unexpected return value");
78 	k_thread_abort(tid);
79 
80 	tid = k_thread_create(&user_thread, ustack, STACK_SIZE, preempt_test_thread,
81 			NULL, NULL, NULL,
82 			K_PRIO_PREEMPT(1),
83 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
84 
85 	k_sem_take(&user_sem, K_FOREVER);
86 
87 	twp = thread_was_preempt;
88 	zassert_true(twp, "unexpected return value");
89 	k_thread_abort(tid);
90 }
91 
92 /**
93  * userspace negative test: take NULL as input param to verify
94  * the api will trigger a fatal exception
95  */
96 #ifdef CONFIG_USERSPACE
thread_suspend_init_null(void * p1,void * p2,void * p3)97 static void thread_suspend_init_null(void *p1, void *p2, void *p3)
98 {
99 	ARG_UNUSED(p1);
100 	ARG_UNUSED(p2);
101 	ARG_UNUSED(p3);
102 
103 	ztest_set_fault_valid(true);
104 	k_thread_suspend(NULL);
105 
106 	/* should not go here */
107 	ztest_test_fail();
108 }
109 
110 /**
111  * @brief Test k_thread_suspend() API
112  *
113  * @details Create a thread and set k_thread_suspend() input param to NULL
114  * will trigger a fatal error.
115  *
116  * @ingroup kernel_sched_tests
117  *
118  * @see k_thread_suspend()
119  */
ZTEST_USER(threads_scheduling,test_k_thread_suspend_init_null)120 ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null)
121 {
122 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
123 			thread_suspend_init_null,
124 			NULL, NULL, NULL,
125 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
126 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
127 
128 	k_thread_join(tid, K_FOREVER);
129 }
130 #else
ZTEST_USER(threads_scheduling,test_k_thread_suspend_init_null)131 ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null)
132 {
133 	ztest_test_skip();
134 }
135 #endif
136 
137 #ifdef CONFIG_USERSPACE
thread_resume_init_null(void * p1,void * p2,void * p3)138 static void thread_resume_init_null(void *p1, void *p2, void *p3)
139 {
140 	ARG_UNUSED(p1);
141 	ARG_UNUSED(p2);
142 	ARG_UNUSED(p3);
143 
144 	ztest_set_fault_valid(true);
145 	k_thread_resume(NULL);
146 
147 	/* should not go here */
148 	ztest_test_fail();
149 }
150 
151 /**
152  * @brief Test k_thread_resume() API
153  *
154  * @details Create a thread and set k_thread_resume() input param to NULL
155  * will trigger a fatal error.
156  *
157  * @ingroup kernel_sched_tests
158  *
159  * @see k_thread_resume()
160  */
ZTEST_USER(threads_scheduling,test_k_thread_resume_init_null)161 ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null)
162 {
163 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
164 			thread_resume_init_null,
165 			NULL, NULL, NULL,
166 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
167 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
168 
169 	k_thread_join(tid, K_FOREVER);
170 }
171 #else
ZTEST_USER(threads_scheduling,test_k_thread_resume_init_null)172 ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null)
173 {
174 	ztest_test_skip();
175 }
176 #endif
177 
178 #ifdef CONFIG_USERSPACE
thread_priority_get_init_null(void * p1,void * p2,void * p3)179 static void thread_priority_get_init_null(void *p1, void *p2, void *p3)
180 {
181 	ARG_UNUSED(p1);
182 	ARG_UNUSED(p2);
183 	ARG_UNUSED(p3);
184 
185 	ztest_set_fault_valid(true);
186 	k_thread_priority_get(NULL);
187 
188 	/* should not go here */
189 	ztest_test_fail();
190 }
191 
192 /**
193  * @brief Test k_thread_priority_get() API
194  *
195  * @details Create a thread and set thread_k_thread_priority_get() param input to
196  * NULL will trigger a fatal error.
197  *
198  * @ingroup kernel_sched_tests
199  *
200  * @see thread_k_thread_priority_get()
201  */
ZTEST_USER(threads_scheduling,test_k_thread_priority_get_init_null)202 ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null)
203 {
204 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
205 			thread_priority_get_init_null,
206 			NULL, NULL, NULL,
207 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
208 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
209 
210 	k_thread_join(tid, K_FOREVER);
211 }
212 #else
ZTEST_USER(threads_scheduling,test_k_thread_priority_get_init_null)213 ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null)
214 {
215 	ztest_test_skip();
216 }
217 #endif
218 
219 #ifdef CONFIG_USERSPACE
thread_priority_set_init_null(void * p1,void * p2,void * p3)220 static void thread_priority_set_init_null(void *p1, void *p2, void *p3)
221 {
222 	ARG_UNUSED(p1);
223 	ARG_UNUSED(p2);
224 	ARG_UNUSED(p3);
225 
226 	ztest_set_fault_valid(true);
227 	k_thread_priority_set(NULL, 0);
228 
229 	/* should not go here */
230 	ztest_test_fail();
231 }
232 
233 /**
234  * @brief Test k_thread_priority_set() API
235  *
236  * @details Create a thread and set k_thread_priority_set() param input to
237  * NULL will trigger a fatal error.
238  *
239  * @ingroup kernel_sched_tests
240  *
241  * @see k_thread_priority_set()
242  */
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_init_null)243 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null)
244 {
245 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
246 			thread_priority_set_init_null,
247 			NULL, NULL, NULL,
248 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
249 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
250 
251 	k_thread_join(tid, K_FOREVER);
252 }
253 #else
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_init_null)254 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null)
255 {
256 	ztest_test_skip();
257 }
258 #endif
259 
260 #ifdef CONFIG_USERSPACE
thread_priority_set_overmax(void * p1,void * p2,void * p3)261 static void thread_priority_set_overmax(void *p1, void *p2, void *p3)
262 {
263 	ARG_UNUSED(p1);
264 	ARG_UNUSED(p2);
265 	ARG_UNUSED(p3);
266 
267 	ztest_set_fault_valid(true);
268 
269 	/* set valid priority value outside the priority range will invoke fatal error */
270 	k_thread_priority_set(k_current_get(), K_LOWEST_APPLICATION_THREAD_PRIO + 1);
271 
272 	/* should not go here */
273 	ztest_test_fail();
274 }
275 
276 /**
277  * @brief Test k_thread_priority_set() API
278  *
279  * @details Check input param range overmax in userspace test.
280  *
281  * @ingroup kernel_sched_tests
282  *
283  * @see k_thread_priority_set()
284  */
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_overmax)285 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax)
286 {
287 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
288 			thread_priority_set_overmax,
289 			NULL, NULL, NULL,
290 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
291 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
292 
293 	k_thread_join(tid, K_FOREVER);
294 }
295 #else
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_overmax)296 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax)
297 {
298 	ztest_test_skip();
299 }
300 #endif
301 
302 #ifdef CONFIG_USERSPACE
thread_priority_set_upgrade(void * p1,void * p2,void * p3)303 static void thread_priority_set_upgrade(void *p1, void *p2, void *p3)
304 {
305 	ARG_UNUSED(p1);
306 	ARG_UNUSED(p2);
307 	ARG_UNUSED(p3);
308 
309 	ztest_set_fault_valid(true);
310 
311 	/* at first, set an valid priority */
312 	k_thread_priority_set(k_current_get(), THREAD_TEST_PRIORITY);
313 	/* it cannot upgraded thread priority in usermode */
314 	k_thread_priority_set(k_current_get(), THREAD_TEST_PRIORITY - 1);
315 
316 	/* should not go here */
317 	ztest_test_fail();
318 }
319 
320 /**
321  * @brief Test k_thread_priority_set() API
322  *
323  * @details Check input param range fail in userspace test.
324  *
325  * @ingroup kernel_sched_tests
326  *
327  * @see k_thread_priority_set()
328  */
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_upgrade)329 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade)
330 {
331 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
332 			thread_priority_set_upgrade,
333 			NULL, NULL, NULL,
334 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
335 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
336 
337 	k_thread_join(tid, K_FOREVER);
338 }
339 #else
ZTEST_USER(threads_scheduling,test_k_thread_priority_set_upgrade)340 ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade)
341 {
342 	ztest_test_skip();
343 }
344 #endif
345 
346 #ifdef CONFIG_USERSPACE
thread_wakeup_init_null(void * p1,void * p2,void * p3)347 static void thread_wakeup_init_null(void *p1, void *p2, void *p3)
348 {
349 	ARG_UNUSED(p1);
350 	ARG_UNUSED(p2);
351 	ARG_UNUSED(p3);
352 
353 	ztest_set_fault_valid(true);
354 	k_wakeup(NULL);
355 
356 	/* should not go here */
357 	ztest_test_fail();
358 }
359 
360 /**
361  * @brief Test k_wakeup() API
362  *
363  * @details Create a thread and set k_wakeup() input param to NULL
364  * will trigger a fatal error
365  *
366  * @ingroup kernel_sched_tests
367  *
368  * @see k_wakeup()
369  */
ZTEST_USER(threads_scheduling,test_k_wakeup_init_null)370 ZTEST_USER(threads_scheduling, test_k_wakeup_init_null)
371 {
372 	k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE,
373 			thread_wakeup_init_null,
374 			NULL, NULL, NULL,
375 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
376 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
377 
378 	k_thread_join(tid, K_FOREVER);
379 }
380 #else
ZTEST_USER(threads_scheduling,test_k_wakeup_init_null)381 ZTEST_USER(threads_scheduling, test_k_wakeup_init_null)
382 {
383 	ztest_test_skip();
384 }
385 #endif
386