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