1 /*
2  * Copyright (c) 2016, 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/irq_offload.h>
9 #include <zephyr/ztest_error_hook.h>
10 
11 
12 /**
13  * @defgroup kernel_semaphore_tests Semaphores
14  * @ingroup all_tests
15  * @{
16  * @}
17  */
18 
19 /* Macro declarations */
20 #define SEM_INIT_VAL (0U)
21 #define SEM_MAX_VAL  (10U)
22 #define THREAD_TEST_PRIORITY 0
23 
24 #define sem_give_from_isr(sema) irq_offload(isr_sem_give, (const void *)sema)
25 #define sem_take_from_isr(sema) irq_offload(isr_sem_take, (const void *)sema)
26 
27 #define SEM_TIMEOUT (K_MSEC(100))
28 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
29 #define TOTAL_THREADS_WAITING (5)
30 
31 #define SEC2MS(s) ((s) * 1000)
32 #define QSEC2MS(s) ((s) * 250)
33 
34 #define expect_k_sem_take(sem, timeout, exp, str) do { \
35 	int _act = k_sem_take((sem), (timeout)); \
36 	int _exp = (exp); \
37 	zassert_equal(_act, _exp, (str), _act, _exp); \
38 } while (0)
39 
40 #define expect_k_sem_init(sem, init, max, exp, str) do { \
41 	int _act = k_sem_init((sem), (init), (max)); \
42 	int _exp = (exp); \
43 	zassert_equal(_act, _exp, (str), _act, _exp); \
44 } while (0)
45 
46 #define expect_k_sem_count_get(sem, exp, str) do { \
47 	unsigned int _act = k_sem_count_get(sem); \
48 	unsigned int _exp = (exp); \
49 	zassert_equal(_act, _exp, (str), _act, _exp); \
50 } while (0)
51 
52 #define expect_k_sem_take_nomsg(sem, timeout, exp) \
53 	expect_k_sem_take((sem), (timeout), (exp), "k_sem_take incorrect return value: %d != %d")
54 #define expect_k_sem_init_nomsg(sem, init, max, exp) \
55 	expect_k_sem_init((sem), (init), (max), (exp), \
56 					  "k_sem_init incorrect return value: %d != %d")
57 #define expect_k_sem_count_get_nomsg(sem, exp) \
58 	expect_k_sem_count_get((sem), (exp), "k_sem_count_get incorrect return value: %u != %u")
59 
60 /* global variable for mutual exclusion test */
61 uint32_t critical_var;
62 
63 struct timeout_info {
64 	uint32_t timeout;
65 	struct k_sem *sema;
66 };
67 
68 /******************************************************************************/
69 /* Kobject declaration */
70 K_SEM_DEFINE(statically_defined_sem, SEM_INIT_VAL, SEM_MAX_VAL);
71 K_SEM_DEFINE(simple_sem, SEM_INIT_VAL, SEM_MAX_VAL);
72 K_SEM_DEFINE(low_prio_sem, SEM_INIT_VAL, SEM_MAX_VAL);
73 K_SEM_DEFINE(mid_prio_sem, SEM_INIT_VAL, SEM_MAX_VAL);
74 K_SEM_DEFINE(high_prio_long_sem, SEM_INIT_VAL, SEM_MAX_VAL);
75 K_SEM_DEFINE(high_prio_sem, SEM_INIT_VAL, SEM_MAX_VAL);
76 K_SEM_DEFINE(multiple_thread_sem, SEM_INIT_VAL, SEM_MAX_VAL);
77 
78 K_THREAD_STACK_DEFINE(stack_1, STACK_SIZE);
79 K_THREAD_STACK_DEFINE(stack_2, STACK_SIZE);
80 K_THREAD_STACK_DEFINE(stack_3, STACK_SIZE);
81 K_THREAD_STACK_DEFINE(stack_4, STACK_SIZE);
82 K_THREAD_STACK_ARRAY_DEFINE(multiple_stack, TOTAL_THREADS_WAITING, STACK_SIZE);
83 K_PIPE_DEFINE(timeout_info_pipe,
84 	      sizeof(struct timeout_info) * TOTAL_THREADS_WAITING, 4);
85 
86 struct k_thread sem_tid_1, sem_tid_2, sem_tid_3, sem_tid_4;
87 struct k_thread multiple_tid[TOTAL_THREADS_WAITING];
88 
89 K_SEM_DEFINE(ksema, SEM_INIT_VAL, SEM_MAX_VAL);
90 struct k_sem msg_sema, mut_sem;
91 static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
92 struct k_thread tdata;
93 
94 /******************************************************************************/
95 /* Helper functions */
96 
sem_give_task(void * p1,void * p2,void * p3)97 void sem_give_task(void *p1, void *p2, void *p3)
98 {
99 	k_sem_give((struct k_sem *)p1);
100 }
101 
sem_reset_take_task(void * p1,void * p2,void * p3)102 void sem_reset_take_task(void *p1, void *p2, void *p3)
103 {
104 	k_sem_reset((struct k_sem *)p1);
105 	zassert_false(k_sem_take((struct k_sem *)p1, K_FOREVER));
106 }
107 
isr_sem_give(const void * semaphore)108 void isr_sem_give(const void *semaphore)
109 {
110 	k_sem_give((struct k_sem *)semaphore);
111 }
112 
tsema_thread_thread(struct k_sem * psem)113 static void tsema_thread_thread(struct k_sem *psem)
114 {
115 	/**TESTPOINT: thread-thread sync via sema*/
116 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
117 				      sem_give_task, psem, NULL, NULL,
118 				      K_PRIO_PREEMPT(0),
119 				      K_USER | K_INHERIT_PERMS, K_NO_WAIT);
120 
121 	expect_k_sem_take_nomsg(psem, K_FOREVER, 0);
122 
123 	/*clean the spawn thread avoid side effect in next TC*/
124 	k_thread_join(tid, K_FOREVER);
125 }
126 
tsema_thread_isr(struct k_sem * psem)127 static void tsema_thread_isr(struct k_sem *psem)
128 {
129 	/**TESTPOINT: thread-isr sync via sema*/
130 	irq_offload(isr_sem_give, (const void *)psem);
131 
132 	expect_k_sem_take_nomsg(psem, K_FOREVER, 0);
133 }
134 
135 
isr_sem_take(const void * semaphore)136 void isr_sem_take(const void *semaphore)
137 {
138 	int ret = k_sem_take((struct k_sem *)semaphore, K_NO_WAIT);
139 
140 	if (ret != 0 && ret != -EBUSY) {
141 		zassert_true(false, "incorrect k_sem_take return: %d", ret);
142 	}
143 }
144 
145 
146 
sem_take_timeout_forever_helper(void * p1,void * p2,void * p3)147 void sem_take_timeout_forever_helper(void *p1, void *p2, void *p3)
148 {
149 	k_sleep(K_MSEC(100));
150 	k_sem_give(&simple_sem);
151 }
152 
sem_take_timeout_isr_helper(void * p1,void * p2,void * p3)153 void sem_take_timeout_isr_helper(void *p1, void *p2, void *p3)
154 {
155 	sem_give_from_isr(&simple_sem);
156 }
157 
sem_take_multiple_low_prio_helper(void * p1,void * p2,void * p3)158 void sem_take_multiple_low_prio_helper(void *p1, void *p2, void *p3)
159 {
160 	expect_k_sem_take_nomsg(&low_prio_sem, K_FOREVER, 0);
161 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
162 
163 	k_sem_give(&low_prio_sem);
164 }
165 
sem_take_multiple_mid_prio_helper(void * p1,void * p2,void * p3)166 void sem_take_multiple_mid_prio_helper(void *p1, void *p2, void *p3)
167 {
168 	expect_k_sem_take_nomsg(&mid_prio_sem, K_FOREVER, 0);
169 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
170 
171 	k_sem_give(&mid_prio_sem);
172 }
173 
sem_take_multiple_high_prio_helper(void * p1,void * p2,void * p3)174 void sem_take_multiple_high_prio_helper(void *p1, void *p2, void *p3)
175 {
176 
177 	expect_k_sem_take_nomsg(&high_prio_sem, K_FOREVER, 0);
178 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
179 
180 	k_sem_give(&high_prio_sem);
181 }
182 
183 /* First function for mutual exclusion test */
sem_queue_mutual_exclusion1(void * p1,void * p2,void * p3)184 void sem_queue_mutual_exclusion1(void *p1, void *p2, void *p3)
185 {
186 	for (int i = 0; i < 1000; i++) {
187 		expect_k_sem_take_nomsg(&mut_sem, K_FOREVER, 0);
188 
189 		/* in that function critical section makes critical var +1 */
190 		uint32_t tmp = critical_var;
191 		critical_var += 1;
192 
193 		/* Check that common value was not changed by another thread,
194 		 * when semaphore is taken by current thread, and no other
195 		 * thread can enter the critical section
196 		 */
197 		zassert_true(critical_var == tmp + 1);
198 		k_sem_give(&mut_sem);
199 	}
200 }
201 
202 /* Second function for mutual exclusion test */
sem_queue_mutual_exclusion2(void * p1,void * p2,void * p3)203 void sem_queue_mutual_exclusion2(void *p1, void *p2, void *p3)
204 {
205 	for (int i = 0; i < 1000; i++) {
206 		expect_k_sem_take_nomsg(&mut_sem, K_FOREVER, 0);
207 
208 		/* in that function critical section makes critical var 0 */
209 		uint32_t tmp = critical_var;
210 		critical_var -= 1;
211 
212 		/* Check that common value was not changed by another thread,
213 		 * when semaphore is taken by current thread, and no other
214 		 * thread can enter the critical section
215 		 */
216 		zassert_true(critical_var == tmp - 1);
217 		k_sem_give(&mut_sem);
218 	}
219 }
220 
sem_take_multiple_high_prio_long_helper(void * p1,void * p2,void * p3)221 void sem_take_multiple_high_prio_long_helper(void *p1, void *p2, void *p3)
222 {
223 	expect_k_sem_take_nomsg(&high_prio_long_sem, K_FOREVER, 0);
224 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
225 
226 	k_sem_give(&high_prio_long_sem);
227 }
228 
229 /**
230  * @ingroup kernel_semaphore_tests
231  * @{
232  */
233 
234 
235 /**
236  * @brief Test semaphore defined at compile time
237  * @details
238  * - Get the semaphore count.
239  * - Verify the semaphore count equals to initialized value.
240  * @ingroup kernel_semaphore_tests
241  * @see k_sem_count_get()
242  */
ZTEST_USER(semaphore,test_k_sem_define)243 ZTEST_USER(semaphore, test_k_sem_define)
244 {
245 	/* verify the semaphore count equals to initialized value */
246 	expect_k_sem_count_get(&statically_defined_sem, SEM_INIT_VAL,
247 		     "semaphore initialized failed at compile time"
248 		     "- got %u, expected %u");
249 }
250 
251 /**
252  * @brief Test synchronization of threads with semaphore
253  * @see k_sem_init(), #K_SEM_DEFINE(x)
254  */
ZTEST_USER(semaphore,test_sem_thread2thread)255 ZTEST_USER(semaphore, test_sem_thread2thread)
256 {
257 	/**TESTPOINT: test k_sem_init sema*/
258 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
259 
260 	tsema_thread_thread(&msg_sema);
261 
262 	/**TESTPOINT: test K_SEM_DEFINE sema*/
263 	tsema_thread_thread(&ksema);
264 }
265 
266 /**
267  * @brief Test synchronization between thread and irq
268  * @see k_sem_init(), #K_SEM_DEFINE(x)
269  */
ZTEST(semaphore,test_sem_thread2isr)270 ZTEST(semaphore, test_sem_thread2isr)
271 {
272 	/**TESTPOINT: test k_sem_init sema*/
273 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
274 
275 	tsema_thread_isr(&msg_sema);
276 
277 	/**TESTPOINT: test K_SEM_DEFINE sema*/
278 	tsema_thread_isr(&ksema);
279 }
280 
281 /**
282  * @brief Test semaphore initialization at runtime
283  * @details
284  * - Initialize a semaphore with valid count and max limit.
285  * - Initialize a semaphore with invalid max limit.
286  * - Initialize a semaphore with invalid count.
287  * @ingroup kernel_semaphore_tests
288  */
ZTEST_USER(semaphore,test_k_sem_init)289 ZTEST_USER(semaphore, test_k_sem_init)
290 {
291 	/* initialize a semaphore with valid count and max limit */
292 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
293 
294 	k_sem_reset(&msg_sema);
295 
296 	/* initialize a semaphore with invalid max limit */
297 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, 0, -EINVAL);
298 
299 	/* initialize a semaphore with invalid count */
300 	expect_k_sem_init_nomsg(&msg_sema, SEM_MAX_VAL + 1, SEM_MAX_VAL, -EINVAL);
301 }
302 
303 
304 /**
305  * @brief Test k_sem_reset() API
306  * @see k_sem_reset()
307  */
ZTEST_USER(semaphore,test_sem_reset)308 ZTEST_USER(semaphore, test_sem_reset)
309 {
310 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
311 	expect_k_sem_count_get_nomsg(&msg_sema, 0);
312 
313 	k_sem_give(&msg_sema);
314 	expect_k_sem_count_get_nomsg(&msg_sema, 1);
315 	k_sem_reset(&msg_sema);
316 	expect_k_sem_count_get_nomsg(&msg_sema, 0);
317 
318 	/**TESTPOINT: semaphore take return -EBUSY*/
319 	expect_k_sem_take_nomsg(&msg_sema, K_NO_WAIT, -EBUSY);
320 	expect_k_sem_count_get_nomsg(&msg_sema, 0);
321 
322 	/**TESTPOINT: semaphore take return -EAGAIN*/
323 	expect_k_sem_take_nomsg(&msg_sema, SEM_TIMEOUT, -EAGAIN);
324 	expect_k_sem_count_get_nomsg(&msg_sema, 0);
325 
326 	k_sem_give(&msg_sema);
327 	expect_k_sem_count_get_nomsg(&msg_sema, 1);
328 
329 	expect_k_sem_take_nomsg(&msg_sema, K_FOREVER, 0);
330 	expect_k_sem_count_get_nomsg(&msg_sema, 0);
331 }
332 
ZTEST_USER(semaphore,test_sem_reset_waiting)333 ZTEST_USER(semaphore, test_sem_reset_waiting)
334 {
335 	int32_t ret_value;
336 
337 	k_sem_reset(&simple_sem);
338 
339 	/* create a new thread. It will reset the semaphore in 1ms
340 	 * then wait for us.
341 	 */
342 	k_tid_t tid = k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
343 			sem_reset_take_task, &simple_sem, NULL, NULL,
344 			K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS,
345 			K_MSEC(1));
346 
347 	/* Take semaphore and wait for the abort. */
348 	ret_value = k_sem_take(&simple_sem, K_FOREVER);
349 	zassert_true(ret_value == -EAGAIN, "k_sem_take not aborted: %d",
350 			ret_value);
351 
352 	/* ensure the semaphore is still functional after. */
353 	k_sem_give(&simple_sem);
354 
355 	k_thread_join(tid, K_FOREVER);
356 }
357 
358 /**
359  * @brief Test k_sem_count_get() API
360  * @see k_sem_count_get()
361  */
ZTEST_USER(semaphore,test_sem_count_get)362 ZTEST_USER(semaphore, test_sem_count_get)
363 {
364 	expect_k_sem_init_nomsg(&msg_sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
365 
366 	/**TESTPOINT: semaphore count get upon init*/
367 	expect_k_sem_count_get_nomsg(&msg_sema, SEM_INIT_VAL);
368 	k_sem_give(&msg_sema);
369 	/**TESTPOINT: sem count get after give*/
370 	expect_k_sem_count_get_nomsg(&msg_sema, SEM_INIT_VAL + 1);
371 	expect_k_sem_take_nomsg(&msg_sema, K_FOREVER, 0);
372 	/**TESTPOINT: sem count get after take*/
373 	for (int i = 0; i < SEM_MAX_VAL; i++) {
374 		expect_k_sem_count_get_nomsg(&msg_sema, SEM_INIT_VAL + i);
375 		k_sem_give(&msg_sema);
376 	}
377 	/**TESTPOINT: semaphore give above limit*/
378 	k_sem_give(&msg_sema);
379 	expect_k_sem_count_get_nomsg(&msg_sema, SEM_MAX_VAL);
380 }
381 
382 
383 /**
384  * @brief Test whether a semaphore can be given by an ISR
385  * @details
386  * - Reset an initialized semaphore's count to zero
387  * - Create a loop, in each loop, do follow steps
388  * - Give the semaphore from an ISR
389  * - Get the semaphore's count
390  * - Verify whether the semaphore's count as expected
391  * @ingroup kernel_semaphore_tests
392  * @see k_sem_give()
393  */
ZTEST(semaphore,test_sem_give_from_isr)394 ZTEST(semaphore, test_sem_give_from_isr)
395 {
396 	/*
397 	 * Signal the semaphore several times from an ISR.  After each signal,
398 	 * check the signal count.
399 	 */
400 
401 	k_sem_reset(&simple_sem);
402 	expect_k_sem_count_get_nomsg(&simple_sem, 0);
403 
404 	for (int i = 0; i < 5; i++) {
405 		sem_give_from_isr(&simple_sem);
406 
407 		expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
408 	}
409 }
410 
411 /**
412  * @brief Test semaphore count when given by thread
413  * @details
414  * - Reset an initialized semaphore's count to zero
415  * - Create a loop, in each loop, do follow steps
416  * - Give the semaphore from a thread
417  * - Get the semaphore's count
418  * - Verify whether the semaphore's count as expected
419  * @ingroup kernel_semaphore_tests
420  * @see k_sem_give()
421  */
ZTEST_USER(semaphore,test_sem_give_from_thread)422 ZTEST_USER(semaphore, test_sem_give_from_thread)
423 {
424 	/*
425 	 * Signal the semaphore several times from a task.  After each signal,
426 	 * check the signal count.
427 	 */
428 
429 	k_sem_reset(&simple_sem);
430 	expect_k_sem_count_get_nomsg(&simple_sem, 0);
431 
432 	for (int i = 0; i < 5; i++) {
433 		k_sem_give(&simple_sem);
434 
435 		expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
436 	}
437 
438 }
439 
440 /**
441  * @brief Test if k_sem_take() decreases semaphore count
442  * @see k_sem_take()
443  */
ZTEST_USER(semaphore,test_sem_take_no_wait)444 ZTEST_USER(semaphore, test_sem_take_no_wait)
445 {
446 	/*
447 	 * Test the semaphore without wait.  Check the signal count after each
448 	 * attempt (it should be decrementing by 1 each time).
449 	 */
450 
451 	k_sem_reset(&simple_sem);
452 	for (int i = 0; i < 5; i++) {
453 		k_sem_give(&simple_sem);
454 	}
455 
456 	for (int i = 4; i >= 0; i--) {
457 		expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, 0);
458 		expect_k_sem_count_get_nomsg(&simple_sem, i);
459 	}
460 }
461 
462 /**
463  * @brief Test k_sem_take() when there is no semaphore to take
464  * @see k_sem_take()
465  */
ZTEST_USER(semaphore,test_sem_take_no_wait_fails)466 ZTEST_USER(semaphore, test_sem_take_no_wait_fails)
467 {
468 	/*
469 	 * Test the semaphore without wait.  Check the signal count after each
470 	 * attempt (it should be always zero).
471 	 */
472 
473 	k_sem_reset(&simple_sem);
474 
475 	for (int i = 4; i >= 0; i--) {
476 		expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
477 		expect_k_sem_count_get_nomsg(&simple_sem, 0);
478 	}
479 
480 }
481 
482 /**
483  * @brief Test a semaphore take operation with an unavailable semaphore
484  * @details
485  * - Reset the semaphore's count to zero, let it unavailable.
486  * - Take an unavailable semaphore and wait it until timeout.
487  * @ingroup kernel_semaphore_tests
488  * @see k_sem_take()
489  */
ZTEST_USER(semaphore,test_sem_take_timeout_fails)490 ZTEST_USER(semaphore, test_sem_take_timeout_fails)
491 {
492 	/*
493 	 * Test the semaphore with timeout without a k_sem_give.
494 	 */
495 	k_sem_reset(&simple_sem);
496 	expect_k_sem_count_get_nomsg(&simple_sem, 0);
497 
498 	/* take an unavailable semaphore and wait it until timeout */
499 	for (int i = 4; i >= 0; i--) {
500 		expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, -EAGAIN);
501 	}
502 }
503 
504 /**
505  * @brief Test the semaphore take operation with specified timeout
506  * @details
507  * - Create a new thread, it will give semaphore.
508  * - Reset the semaphore's count to zero.
509  * - Take semaphore and wait it given by other threads in specified timeout.
510  * @ingroup kernel_semaphore_tests
511  * @see k_sem_take()
512  */
ZTEST_USER(semaphore,test_sem_take_timeout)513 ZTEST_USER(semaphore, test_sem_take_timeout)
514 {
515 	/*
516 	 * Signal the semaphore upon which the other thread is waiting.
517 	 * The thread (which is at a lower priority) will cause simple_sem
518 	 * to be signalled, thus waking up this task.
519 	 */
520 
521 	/* create a new thread, it will give semaphore */
522 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
523 			sem_give_task, &simple_sem, NULL, NULL,
524 			K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS,
525 			K_FOREVER);
526 
527 	k_sem_reset(&simple_sem);
528 
529 	expect_k_sem_count_get_nomsg(&simple_sem, 0);
530 
531 	k_thread_start(&sem_tid_1);
532 	/* Take semaphore and wait it given by other threads
533 	 * in specified timeout
534 	 */
535 	expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, 0);
536 	k_thread_join(&sem_tid_1, K_FOREVER);
537 }
538 
539 /**
540  * @brief Test the semaphore take operation with forever wait
541  * @details
542  * - Create a new thread, it will give semaphore.
543  * - Reset the semaphore's count to zero.
544  * - Take semaphore, wait it given by other thread forever until it's available.
545  * @ingroup kernel_semaphore_tests
546  * @see k_sem_take()
547  */
ZTEST_USER(semaphore,test_sem_take_timeout_forever)548 ZTEST_USER(semaphore, test_sem_take_timeout_forever)
549 {
550 	/*
551 	 * Signal the semaphore upon which the another thread is waiting.  The
552 	 * thread (which is at a lower priority) will cause simple_sem
553 	 * to be signalled, thus waking this task.
554 	 */
555 
556 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
557 			sem_take_timeout_forever_helper, NULL, NULL, NULL,
558 			K_PRIO_PREEMPT(0), K_USER | K_INHERIT_PERMS,
559 			K_NO_WAIT);
560 
561 	k_sem_reset(&simple_sem);
562 
563 	expect_k_sem_count_get_nomsg(&simple_sem, 0);
564 
565 	/* Take semaphore and wait it given by
566 	 * other threads forever until it's available
567 	 */
568 	expect_k_sem_take_nomsg(&simple_sem, K_FOREVER, 0);
569 	k_thread_join(&sem_tid_1, K_FOREVER);
570 }
571 
572 /**
573  * @brief Test k_sem_take() with timeout in ISR context
574  * @see k_sem_take()
575  */
ZTEST(semaphore_1cpu,test_sem_take_timeout_isr)576 ZTEST(semaphore_1cpu, test_sem_take_timeout_isr)
577 {
578 	/*
579 	 * Signal the semaphore upon which the another thread is waiting.  The
580 	 * thread (which is at a lower priority) will cause simple_sem
581 	 * to be signalled, thus waking this task.
582 	 */
583 
584 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
585 			sem_take_timeout_isr_helper, NULL, NULL, NULL,
586 			K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
587 
588 	k_sem_reset(&simple_sem);
589 
590 	expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, 0);
591 
592 	k_thread_join(&sem_tid_1, K_FOREVER);
593 }
594 
595 /**
596  * @brief Test semaphore take operation by multiple threads
597  * @ingroup kernel_semaphore_tests
598  * @see k_sem_take()
599  */
ZTEST_USER(semaphore,test_sem_take_multiple)600 ZTEST_USER(semaphore, test_sem_take_multiple)
601 {
602 	k_sem_reset(&multiple_thread_sem);
603 	k_sem_reset(&high_prio_long_sem);
604 	k_sem_reset(&mid_prio_sem);
605 	k_sem_reset(&low_prio_sem);
606 	k_sem_reset(&high_prio_sem);
607 	expect_k_sem_count_get_nomsg(&multiple_thread_sem, 0);
608 	expect_k_sem_count_get_nomsg(&high_prio_long_sem, 0);
609 	expect_k_sem_count_get_nomsg(&mid_prio_sem, 0);
610 	expect_k_sem_count_get_nomsg(&low_prio_sem, 0);
611 	expect_k_sem_count_get_nomsg(&high_prio_sem, 0);
612 	/*
613 	 * Signal the semaphore upon which the another thread is waiting.
614 	 * The thread (which is at a lower priority) will cause simple_sem
615 	 * to be signalled, thus waking this task.
616 	 */
617 
618 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
619 			sem_take_multiple_low_prio_helper,
620 			NULL, NULL, NULL,
621 			K_PRIO_PREEMPT(3), K_USER | K_INHERIT_PERMS,
622 			K_NO_WAIT);
623 
624 	k_thread_create(&sem_tid_2, stack_2, STACK_SIZE,
625 			sem_take_multiple_mid_prio_helper,
626 			NULL, NULL, NULL,
627 			K_PRIO_PREEMPT(2), K_USER | K_INHERIT_PERMS,
628 			K_NO_WAIT);
629 
630 	k_thread_create(&sem_tid_3, stack_3, STACK_SIZE,
631 			sem_take_multiple_high_prio_long_helper,
632 			NULL, NULL, NULL,
633 			K_PRIO_PREEMPT(1), K_USER | K_INHERIT_PERMS,
634 			K_NO_WAIT);
635 
636 	/* Create another high priority thread, the same priority with sem_tid_3
637 	 * sem_tid_3 and sem_tid_4 are the same highest priority,
638 	 * but the waiting time of sem_tid_3 is longer than sem_tid_4.
639 	 * If some threads are the same priority, the sem given operation
640 	 * should be decided according to waiting time.
641 	 * That thread is necessary to test if a sem is available,
642 	 * it should be given to the highest priority and longest waiting thread
643 	 */
644 	k_thread_create(&sem_tid_4, stack_4, STACK_SIZE,
645 			sem_take_multiple_high_prio_helper, NULL, NULL,
646 			NULL, K_PRIO_PREEMPT(1), K_USER | K_INHERIT_PERMS,
647 			K_NO_WAIT);
648 
649 	/* time for those 4 threads to complete */
650 	k_sleep(K_MSEC(20));
651 
652 	/* Let these threads proceed to take the multiple_sem
653 	 * make thread 1 to 3 waiting on multiple_thread_sem
654 	 */
655 	k_sem_give(&high_prio_long_sem);
656 	k_sem_give(&mid_prio_sem);
657 	k_sem_give(&low_prio_sem);
658 
659 	/* Delay 100ms to make sem_tid_4 waiting on multiple_thread_sem,
660 	 * then waiting time of sem_tid_4 is shorter than sem_tid_3
661 	 */
662 	k_sleep(K_MSEC(100));
663 	k_sem_give(&high_prio_sem);
664 
665 	k_sleep(K_MSEC(20));
666 
667 	/* enable the high prio and long waiting thread sem_tid_3 to run */
668 	k_sem_give(&multiple_thread_sem);
669 	k_sleep(K_MSEC(200));
670 
671 	/* check which threads completed */
672 	expect_k_sem_count_get(&high_prio_long_sem, 1,
673 			"High priority and long waiting thread "
674 			"don't get the sem: %u != %u");
675 
676 	expect_k_sem_count_get(&high_prio_sem, 0U,
677 			"High priority thread shouldn't get the sem: %u != %u");
678 
679 	expect_k_sem_count_get(&mid_prio_sem, 0U,
680 		"Medium priority threads shouldn't have executed: %u != %u");
681 
682 	expect_k_sem_count_get(&low_prio_sem, 0U,
683 		"Low priority threads shouldn't have executed: %u != %u");
684 
685 	/* enable the high prio thread sem_tid_4 to run */
686 	k_sem_give(&multiple_thread_sem);
687 	k_sleep(K_MSEC(200));
688 
689 	/* check which threads completed */
690 	expect_k_sem_count_get(&high_prio_long_sem, 1U,
691 		"High priority and long waiting thread executed again: %u != %u");
692 
693 	expect_k_sem_count_get(&high_prio_sem, 1U,
694 		"Higher priority thread did not get the sem: %u != %u");
695 
696 	expect_k_sem_count_get(&mid_prio_sem, 0U,
697 		"Medium priority thread shouldn't get the sem: %u != %u");
698 
699 	expect_k_sem_count_get(&low_prio_sem, 0U,
700 		"Low priority thread shouldn't get the sem: %u != %u");
701 
702 	/* enable the mid prio thread sem_tid_2 to run */
703 	k_sem_give(&multiple_thread_sem);
704 	k_sleep(K_MSEC(200));
705 
706 	/* check which threads completed */
707 	expect_k_sem_count_get(&high_prio_long_sem, 1U,
708 		"High priority and long waiting thread executed again: %u != %u");
709 
710 	expect_k_sem_count_get(&high_prio_sem, 1U,
711 		"High priority thread executed again: %u != %u");
712 
713 	expect_k_sem_count_get(&mid_prio_sem, 1U,
714 		"Medium priority thread did not get the sem: %u != %u");
715 
716 	expect_k_sem_count_get(&low_prio_sem, 0U,
717 		"Low priority thread did not get the sem: %u != %u");
718 
719 	/* enable the low prio thread(thread_1) to run */
720 	k_sem_give(&multiple_thread_sem);
721 	k_sleep(K_MSEC(200));
722 
723 	/* check the thread completed */
724 	expect_k_sem_count_get(&high_prio_long_sem, 1U,
725 		"High priority and long waiting thread executed again: %u != %u");
726 
727 	expect_k_sem_count_get(&high_prio_sem, 1U,
728 		"High priority thread executed again: %u != %u");
729 
730 	expect_k_sem_count_get(&mid_prio_sem, 1U,
731 		"Mid priority thread executed again: %u != %u");
732 
733 	expect_k_sem_count_get(&low_prio_sem, 1U,
734 		"Low priority thread did not get the sem: %u != %u");
735 
736 	k_thread_join(&sem_tid_1, K_FOREVER);
737 	k_thread_join(&sem_tid_2, K_FOREVER);
738 	k_thread_join(&sem_tid_3, K_FOREVER);
739 	k_thread_join(&sem_tid_4, K_FOREVER);
740 }
741 
742 /**
743  * @brief Test the max value a semaphore can be given and taken
744  * @details
745  * - Reset an initialized semaphore's count to zero.
746  * - Give the semaphore by a thread and verify the semaphore's count is
747  *   as expected.
748  * - Verify the max count a semaphore can reach.
749  * - Take the semaphore by a thread and verify the semaphore's count is
750  *   as expected.
751  * - Verify the max times a semaphore can be taken.
752  * @ingroup kernel_semaphore_tests
753  * @see k_sem_count_get(), k_sem_give()
754  */
ZTEST_USER(semaphore,test_k_sem_correct_count_limit)755 ZTEST_USER(semaphore, test_k_sem_correct_count_limit)
756 {
757 
758 	/* reset an initialized semaphore's count to zero */
759 	k_sem_reset(&simple_sem);
760 	expect_k_sem_count_get(&simple_sem, 0U, "k_sem_reset failed: %u != %u");
761 
762 	/* Give the semaphore by a thread and verify the semaphore's
763 	 * count is as expected
764 	 */
765 	for (int i = 1; i <= SEM_MAX_VAL; i++) {
766 		k_sem_give(&simple_sem);
767 		expect_k_sem_count_get_nomsg(&simple_sem, i);
768 	}
769 
770 	/* Verify the max count a semaphore can reach
771 	 * continue to run k_sem_give,
772 	 * the count of simple_sem will not increase anymore
773 	 */
774 	for (int i = 0; i < 5; i++) {
775 		k_sem_give(&simple_sem);
776 		expect_k_sem_count_get_nomsg(&simple_sem, SEM_MAX_VAL);
777 	}
778 
779 	/* Take the semaphore by a thread and verify the semaphore's
780 	 * count is as expected
781 	 */
782 	for (int i = SEM_MAX_VAL - 1; i >= 0; i--) {
783 		expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, 0);
784 		expect_k_sem_count_get_nomsg(&simple_sem, i);
785 	}
786 
787 	/* Verify the max times a semaphore can be taken
788 	 * continue to run k_sem_take, simple_sem can not be taken and
789 	 * it's count will be zero
790 	 */
791 	for (int i = 0; i < 5; i++) {
792 		expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
793 
794 		expect_k_sem_count_get_nomsg(&simple_sem, 0U);
795 	}
796 }
797 
798 /**
799  * @brief Test semaphore give and take and its count from ISR
800  * @see k_sem_give()
801  */
ZTEST(semaphore,test_sem_give_take_from_isr)802 ZTEST(semaphore, test_sem_give_take_from_isr)
803 {
804 	k_sem_reset(&simple_sem);
805 	expect_k_sem_count_get_nomsg(&simple_sem, 0U);
806 
807 	/* give semaphore from an isr and do a check for the count */
808 	for (int i = 0; i < SEM_MAX_VAL; i++) {
809 		sem_give_from_isr(&simple_sem);
810 		expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
811 	}
812 
813 	/* take semaphore from an isr and do a check for the count */
814 	for (int i = SEM_MAX_VAL; i > 0; i--) {
815 		sem_take_from_isr(&simple_sem);
816 
817 		expect_k_sem_count_get_nomsg(&simple_sem, i - 1);
818 	}
819 }
820 
821 /**
822  * @}
823  */
824 
sem_multiple_threads_wait_helper(void * p1,void * p2,void * p3)825 void sem_multiple_threads_wait_helper(void *p1, void *p2, void *p3)
826 {
827 	/* get blocked until the test thread gives the semaphore */
828 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
829 
830 	/* inform the test thread that this thread has got multiple_thread_sem*/
831 	k_sem_give(&simple_sem);
832 }
833 
834 
835 /**
836  * @brief Test multiple semaphore take and give with wait
837  * @ingroup kernel_semaphore_tests
838  * @see k_sem_take(), k_sem_give()
839  */
ZTEST(semaphore,test_sem_multiple_threads_wait)840 ZTEST(semaphore, test_sem_multiple_threads_wait)
841 {
842 	k_sem_reset(&simple_sem);
843 	k_sem_reset(&multiple_thread_sem);
844 
845 	/* Verify a wait q that has been emptied / reset
846 	 * correctly by running twice.
847 	 */
848 	for (int repeat_count = 0; repeat_count < 2; repeat_count++) {
849 		for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
850 			k_thread_create(&multiple_tid[i],
851 					multiple_stack[i], STACK_SIZE,
852 					sem_multiple_threads_wait_helper,
853 					NULL, NULL, NULL,
854 					K_PRIO_PREEMPT(1),
855 					K_USER | K_INHERIT_PERMS, K_NO_WAIT);
856 		}
857 
858 		/* giving time for the other threads to execute  */
859 		k_sleep(K_MSEC(500));
860 
861 		/* give the semaphores */
862 		for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
863 			k_sem_give(&multiple_thread_sem);
864 		}
865 
866 		/* giving time for the other threads to execute  */
867 		k_sleep(K_MSEC(500));
868 
869 		/* check if all the threads are done. */
870 		for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
871 			expect_k_sem_take(&simple_sem, K_FOREVER, 0,
872 				"Some of the threads did not get multiple_thread_sem: %d != %d");
873 		}
874 
875 		expect_k_sem_count_get_nomsg(&simple_sem, 0U);
876 		expect_k_sem_count_get_nomsg(&multiple_thread_sem, 0U);
877 
878 	}
879 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
880 		k_thread_join(&multiple_tid[i], K_FOREVER);
881 	}
882 }
883 
884 /**
885  * @brief Test semaphore timeout period
886  * @ingroup kernel_semaphore_tests
887  * @see k_sem_take(), k_sem_give(), k_sem_reset()
888  */
ZTEST(semaphore,test_sem_measure_timeouts)889 ZTEST(semaphore, test_sem_measure_timeouts)
890 {
891 	int64_t start_ticks, end_ticks, diff_ticks;
892 
893 	k_sem_reset(&simple_sem);
894 
895 	/* with timeout of 1 sec */
896 	start_ticks = k_uptime_get();
897 
898 	expect_k_sem_take_nomsg(&simple_sem, K_SECONDS(1), -EAGAIN);
899 
900 	end_ticks = k_uptime_get();
901 
902 	diff_ticks = end_ticks - start_ticks;
903 
904 	zassert_true((diff_ticks >= SEC2MS(1)),
905 		     "k_sem_take returned too early: %lld < %d",
906 		     diff_ticks, SEC2MS(1));
907 
908 	/* This subtest could fail spuriously if we happened to run the below right as
909 	 * a tick occurred. Unfortunately, we cannot actually fix this, because on some
910 	 * emulated platforms time does not advance while running the cpu, so
911 	 * if we spin and wait for a tick boundary we'll spin forever.
912 	 * The best we can do is hope that k_busy_wait finishes just after a tick boundary.
913 	 */
914 	k_busy_wait(1);
915 	start_ticks = k_uptime_get();
916 
917 	expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
918 
919 	end_ticks = k_uptime_get();
920 
921 	diff_ticks = end_ticks - start_ticks;
922 
923 	zassert_true(end_ticks >= start_ticks,
924 		     "time went backwards: %lld -> %lld",
925 		     start_ticks, end_ticks);
926 
927 	zassert_true(diff_ticks >= 0,
928 		     "k_sem_take took too long: %lld != 0",
929 		     diff_ticks);
930 }
931 
sem_measure_timeout_from_thread_helper(void * p1,void * p2,void * p3)932 void sem_measure_timeout_from_thread_helper(void *p1, void *p2, void *p3)
933 {
934 	/* first sync the 2 threads */
935 	k_sem_give(&simple_sem);
936 
937 	/* give the semaphore */
938 	k_sem_give(&multiple_thread_sem);
939 }
940 
941 
942 /**
943  * @brief Test timeout of semaphore from thread
944  * @ingroup kernel_semaphore_tests
945  * @see k_sem_give(), k_sem_reset(), k_sem_take()
946  */
ZTEST(semaphore,test_sem_measure_timeout_from_thread)947 ZTEST(semaphore, test_sem_measure_timeout_from_thread)
948 {
949 	int64_t start_ticks, end_ticks, diff_ticks;
950 
951 	k_sem_reset(&simple_sem);
952 	k_sem_reset(&multiple_thread_sem);
953 
954 	/* give a semaphore from a thread and calculate the time taken */
955 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
956 			sem_measure_timeout_from_thread_helper,
957 			NULL, NULL, NULL,
958 			K_PRIO_PREEMPT(3), 0, K_NO_WAIT);
959 
960 
961 	/* first sync the 2 threads */
962 	expect_k_sem_take_nomsg(&simple_sem, K_FOREVER, 0);
963 
964 	/* with timeout of 1 sec */
965 	start_ticks = k_uptime_get();
966 
967 	expect_k_sem_take_nomsg(&multiple_thread_sem, K_SECONDS(1), 0);
968 
969 	end_ticks = k_uptime_get();
970 
971 	diff_ticks = end_ticks - start_ticks;
972 
973 	zassert_true((diff_ticks < SEC2MS(1)),
974 		     "k_sem_take took too long: %d >= %d",
975 		     diff_ticks, SEC2MS(1));
976 	k_thread_join(&sem_tid_1, K_FOREVER);
977 }
978 
sem_multiple_take_and_timeouts_helper(void * p1,void * p2,void * p3)979 void sem_multiple_take_and_timeouts_helper(void *p1, void *p2, void *p3)
980 {
981 	int timeout = POINTER_TO_INT(p1);
982 	int64_t start_ticks, end_ticks, diff_ticks;
983 
984 	start_ticks = k_uptime_get();
985 
986 	expect_k_sem_take_nomsg(&simple_sem, K_MSEC(timeout), -EAGAIN);
987 
988 	end_ticks = k_uptime_get();
989 
990 	diff_ticks = end_ticks - start_ticks;
991 
992 	zassert_true(diff_ticks >= timeout,
993 		     "time mismatch - expected at least %d, got %lld",
994 		     timeout, diff_ticks);
995 
996 	k_pipe_write(&timeout_info_pipe, (uint8_t *)&timeout, sizeof(int), K_FOREVER);
997 
998 }
999 
1000 /**
1001  * @brief Test multiple semaphore take with timeouts
1002  * @ingroup kernel_semaphore_tests
1003  * @see k_sem_take(), k_sem_reset()
1004  */
ZTEST(semaphore_1cpu,test_sem_multiple_take_and_timeouts)1005 ZTEST(semaphore_1cpu, test_sem_multiple_take_and_timeouts)
1006 {
1007 	if (IS_ENABLED(CONFIG_KERNEL_COHERENCE)) {
1008 		ztest_test_skip();
1009 	}
1010 
1011 	static uint32_t timeout;
1012 
1013 	k_sem_reset(&simple_sem);
1014 	k_pipe_reset(&timeout_info_pipe);
1015 
1016 	/* Multiple threads timeout and the sequence in which it times out
1017 	 * is pushed into a pipe and checked later on.
1018 	 */
1019 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1020 		k_thread_create(&multiple_tid[i],
1021 				multiple_stack[i], STACK_SIZE,
1022 				sem_multiple_take_and_timeouts_helper,
1023 				INT_TO_POINTER(QSEC2MS(i + 1)), NULL, NULL,
1024 				K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
1025 	}
1026 
1027 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1028 		k_pipe_read(&timeout_info_pipe, (uint8_t *)&timeout, sizeof(int), K_FOREVER);
1029 		zassert_equal(timeout, QSEC2MS(i + 1),
1030 			     "timeout did not occur properly: %d != %d",
1031 				 timeout, QSEC2MS(i + 1));
1032 	}
1033 
1034 	/* cleanup */
1035 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1036 		k_thread_join(&multiple_tid[i], K_FOREVER);
1037 	}
1038 }
1039 
sem_multi_take_timeout_diff_sem_helper(void * p1,void * p2,void * p3)1040 void sem_multi_take_timeout_diff_sem_helper(void *p1, void *p2, void *p3)
1041 {
1042 	int rc;
1043 	int timeout = POINTER_TO_INT(p1);
1044 	struct k_sem *sema = p2;
1045 	int64_t start_ticks, end_ticks, diff_ticks;
1046 	struct timeout_info info = {
1047 		.timeout = timeout,
1048 		.sema = sema
1049 	};
1050 
1051 	start_ticks = k_uptime_get();
1052 
1053 	expect_k_sem_take_nomsg(sema, K_MSEC(timeout), -EAGAIN);
1054 
1055 	end_ticks = k_uptime_get();
1056 
1057 	diff_ticks = end_ticks - start_ticks;
1058 
1059 	zassert_true(diff_ticks >= timeout,
1060 		     "time mismatch - expected at least %d, got %lld",
1061 		     timeout, diff_ticks);
1062 
1063 	rc = k_pipe_write(&timeout_info_pipe, (uint8_t *)&info, sizeof(struct timeout_info),
1064 		   K_FOREVER);
1065 	zassert_true(rc == sizeof(struct timeout_info),
1066 		     "k_pipe_write failed: %d", rc);
1067 }
1068 
1069 /**
1070  * @brief Test sequence of multiple semaphore timeouts
1071  * @ingroup kernel_semaphore_tests
1072  * @see k_sem_take(), k_sem_reset()
1073  */
ZTEST(semaphore,test_sem_multi_take_timeout_diff_sem)1074 ZTEST(semaphore, test_sem_multi_take_timeout_diff_sem)
1075 {
1076 	int rc;
1077 	if (IS_ENABLED(CONFIG_KERNEL_COHERENCE)) {
1078 		ztest_test_skip();
1079 	}
1080 
1081 	struct timeout_info seq_info[] = {
1082 		{ SEC2MS(2), &simple_sem },
1083 		{ SEC2MS(1), &multiple_thread_sem },
1084 		{ SEC2MS(3), &simple_sem },
1085 		{ SEC2MS(5), &multiple_thread_sem },
1086 		{ SEC2MS(4), &simple_sem },
1087 	};
1088 
1089 	static struct timeout_info retrieved_info;
1090 
1091 	k_sem_reset(&simple_sem);
1092 	k_sem_reset(&multiple_thread_sem);
1093 	k_pipe_reset(&timeout_info_pipe);
1094 	memset(&retrieved_info, 0, sizeof(struct timeout_info));
1095 
1096 	/* Multiple threads timeout on different semaphores and the sequence
1097 	 * in which it times out is pushed into a pipe and checked later on.
1098 	 */
1099 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1100 		k_thread_create(&multiple_tid[i],
1101 				multiple_stack[i], STACK_SIZE,
1102 				sem_multi_take_timeout_diff_sem_helper,
1103 				INT_TO_POINTER(seq_info[i].timeout),
1104 				seq_info[i].sema, NULL,
1105 				K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
1106 	}
1107 
1108 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1109 		rc = k_pipe_read(&timeout_info_pipe, (uint8_t *)&retrieved_info,
1110 			sizeof(struct timeout_info), K_FOREVER);
1111 		zassert_true(rc == sizeof(struct timeout_info),
1112 			     "k_pipe_read failed: %d", rc);
1113 
1114 		zassert_true(retrieved_info.timeout == SEC2MS(i + 1),
1115 			     "timeout did not occur properly");
1116 	}
1117 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
1118 		k_thread_join(&multiple_tid[i], K_FOREVER);
1119 	}
1120 }
1121 
1122 /**
1123  * @brief Test thread mutual exclusion by semaphore
1124  * @details Test is using to see how mutual exclusion is made by semaphore
1125  * Made two threads, with two functions which use common variable.
1126  * That variable is a critical section and can't be changed by two threads
1127  * at the same time.
1128  * @ingroup kernel_semaphore_tests
1129  */
ZTEST(semaphore_1cpu,test_sem_queue_mutual_exclusion)1130 ZTEST(semaphore_1cpu, test_sem_queue_mutual_exclusion)
1131 {
1132 	critical_var = 0;
1133 
1134 	expect_k_sem_init_nomsg(&mut_sem, 0, 1, 0);
1135 
1136 	k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
1137 			sem_queue_mutual_exclusion1, NULL, NULL,
1138 			NULL, 1, 0,
1139 			K_NO_WAIT);
1140 
1141 	k_thread_create(&sem_tid_2, stack_2, STACK_SIZE,
1142 			sem_queue_mutual_exclusion2, NULL, NULL,
1143 			NULL, 1, 0,
1144 			K_NO_WAIT);
1145 
1146 	k_sleep(K_MSEC(100));
1147 
1148 	k_sem_give(&mut_sem);
1149 	k_thread_join(&sem_tid_1, K_FOREVER);
1150 	k_thread_join(&sem_tid_2, K_FOREVER);
1151 }
1152 
1153 #ifdef CONFIG_USERSPACE
thread_sem_give_null(void * p1,void * p2,void * p3)1154 static void thread_sem_give_null(void *p1, void *p2, void *p3)
1155 {
1156 	ARG_UNUSED(p1);
1157 	ARG_UNUSED(p2);
1158 	ARG_UNUSED(p3);
1159 
1160 	ztest_set_fault_valid(true);
1161 	k_sem_give(NULL);
1162 
1163 	/* should not go here*/
1164 	ztest_test_fail();
1165 }
1166 
1167 /**
1168  * @brief Test k_sem_give() API
1169  *
1170  * @details Create a thread and set k_sem_give() input to NULL
1171  *
1172  * @ingroup kernel_semaphore_tests
1173  *
1174  * @see k_sem_give()
1175  */
ZTEST_USER(semaphore_null_case,test_sem_give_null)1176 ZTEST_USER(semaphore_null_case, test_sem_give_null)
1177 {
1178 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
1179 			thread_sem_give_null,
1180 			NULL, NULL, NULL,
1181 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
1182 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
1183 
1184 	k_thread_join(tid, K_FOREVER);
1185 }
1186 #endif
1187 
1188 #ifdef CONFIG_USERSPACE
thread_sem_init_null(void * p1,void * p2,void * p3)1189 static void thread_sem_init_null(void *p1, void *p2, void *p3)
1190 {
1191 	ARG_UNUSED(p1);
1192 	ARG_UNUSED(p2);
1193 	ARG_UNUSED(p3);
1194 
1195 	ztest_set_fault_valid(true);
1196 	k_sem_init(NULL, 0, 1);
1197 
1198 	/* should not go here*/
1199 	ztest_test_fail();
1200 }
1201 
1202 /**
1203  * @brief Test k_sem_init() API
1204  *
1205  * @details Create a thread and set k_sem_init() input to NULL
1206  *
1207  * @ingroup kernel_semaphore_tests
1208  *
1209  * @see k_sem_init()
1210  */
ZTEST_USER(semaphore_null_case,test_sem_init_null)1211 ZTEST_USER(semaphore_null_case, test_sem_init_null)
1212 {
1213 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
1214 			thread_sem_init_null,
1215 			NULL, NULL, NULL,
1216 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
1217 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
1218 
1219 	k_thread_join(tid, K_FOREVER);
1220 }
1221 #endif
1222 
1223 #ifdef CONFIG_USERSPACE
thread_sem_take_null(void * p1,void * p2,void * p3)1224 static void thread_sem_take_null(void *p1, void *p2, void *p3)
1225 {
1226 	ARG_UNUSED(p1);
1227 	ARG_UNUSED(p2);
1228 	ARG_UNUSED(p3);
1229 
1230 	ztest_set_fault_valid(true);
1231 	k_sem_take(NULL, K_MSEC(1));
1232 
1233 	/* should not go here*/
1234 	ztest_test_fail();
1235 }
1236 
1237 /**
1238  * @brief Test k_sem_take() API
1239  *
1240  * @details Create a thread and set k_sem_take() input to NULL
1241  *
1242  * @ingroup kernel_semaphore_tests
1243  *
1244  * @see k_sem_take()
1245  */
ZTEST_USER(semaphore_null_case,test_sem_take_null)1246 ZTEST_USER(semaphore_null_case, test_sem_take_null)
1247 {
1248 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
1249 			thread_sem_take_null,
1250 			NULL, NULL, NULL,
1251 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
1252 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
1253 
1254 	k_thread_join(tid, K_FOREVER);
1255 }
1256 #endif
1257 
1258 #ifdef CONFIG_USERSPACE
thread_sem_reset_null(void * p1,void * p2,void * p3)1259 static void thread_sem_reset_null(void *p1, void *p2, void *p3)
1260 {
1261 	ARG_UNUSED(p1);
1262 	ARG_UNUSED(p2);
1263 	ARG_UNUSED(p3);
1264 
1265 	ztest_set_fault_valid(true);
1266 	k_sem_reset(NULL);
1267 
1268 	/* should not go here*/
1269 	ztest_test_fail();
1270 }
1271 
1272 /**
1273  * @brief Test k_sem_reset() API
1274  *
1275  * @details Create a thread and set k_sem_reset() input to NULL
1276  *
1277  * @ingroup kernel_semaphore_tests
1278  *
1279  * @see k_sem_reset()
1280  */
ZTEST_USER(semaphore_null_case,test_sem_reset_null)1281 ZTEST_USER(semaphore_null_case, test_sem_reset_null)
1282 {
1283 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
1284 			thread_sem_reset_null,
1285 			NULL, NULL, NULL,
1286 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
1287 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
1288 
1289 	k_thread_join(tid, K_FOREVER);
1290 }
1291 #endif
1292 
1293 #ifdef CONFIG_USERSPACE
thread_sem_count_get_null(void * p1,void * p2,void * p3)1294 static void thread_sem_count_get_null(void *p1, void *p2, void *p3)
1295 {
1296 	ARG_UNUSED(p1);
1297 	ARG_UNUSED(p2);
1298 	ARG_UNUSED(p3);
1299 
1300 	ztest_set_fault_valid(true);
1301 	k_sem_count_get(NULL);
1302 
1303 	/* should not go here*/
1304 	ztest_test_fail();
1305 }
1306 
1307 /**
1308  * @brief Test k_sem_count_get() API
1309  *
1310  * @details Create a thread and set k_sem_count_get() input to NULL
1311  *
1312  * @ingroup kernel_semaphore_tests
1313  *
1314  * @see k_sem_count_get()
1315  */
ZTEST_USER(semaphore_null_case,test_sem_count_get_null)1316 ZTEST_USER(semaphore_null_case, test_sem_count_get_null)
1317 {
1318 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
1319 			thread_sem_count_get_null,
1320 			NULL, NULL, NULL,
1321 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
1322 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
1323 
1324 	k_thread_join(tid, K_FOREVER);
1325 }
1326 #endif
1327 
test_init(void)1328 void *test_init(void)
1329 {
1330 #ifdef CONFIG_USERSPACE
1331 	k_thread_access_grant(k_current_get(),
1332 			      &simple_sem, &multiple_thread_sem, &low_prio_sem,
1333 				  &mid_prio_sem, &high_prio_sem, &ksema, &msg_sema,
1334 				  &high_prio_long_sem, &stack_1, &stack_2,
1335 				  &stack_3, &stack_4, &timeout_info_pipe,
1336 				  &sem_tid_1, &sem_tid_2, &sem_tid_3,
1337 				  &sem_tid_4, &tstack, &tdata, &mut_sem,
1338 				  &statically_defined_sem);
1339 #endif
1340 	return NULL;
1341 }
1342 
1343 ZTEST_SUITE(semaphore, NULL, test_init, NULL, NULL, NULL);
1344 ZTEST_SUITE(semaphore_1cpu, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
1345 ZTEST_SUITE(semaphore_null_case, NULL, test_init, NULL, NULL, NULL);
1346