1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #include <zephyr/ztest.h>
9 #include <zephyr/irq_offload.h>
10 #include <zephyr/ztest_error_hook.h>
11 
12 #define STACK_SIZE     (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
13 
14 #define PRIO_WAIT (CONFIG_ZTEST_THREAD_PRIORITY)
15 #define PRIO_WAKE (CONFIG_ZTEST_THREAD_PRIORITY)
16 
17 K_THREAD_STACK_DEFINE(stack_1, STACK_SIZE);
18 K_THREAD_STACK_DEFINE(condvar_wake_stack, STACK_SIZE);
19 
20 struct k_thread condvar_tid;
21 struct k_thread condvar_wake_tid;
22 
23 struct k_condvar simple_condvar;
24 K_MUTEX_DEFINE(test_mutex);
25 
26 #define TOTAL_THREADS_WAITING (3)
27 #define TCOUNT 10
28 #define COUNT_LIMIT 12
29 
30 ZTEST_BMEM int woken;
31 ZTEST_BMEM int timeout;
32 ZTEST_BMEM int index[TOTAL_THREADS_WAITING];
33 ZTEST_BMEM int count;
34 
35 struct k_condvar multiple_condvar[TOTAL_THREADS_WAITING];
36 
37 struct k_thread multiple_tid[TOTAL_THREADS_WAITING];
38 struct k_thread multiple_wake_tid[TOTAL_THREADS_WAITING];
39 K_THREAD_STACK_ARRAY_DEFINE(multiple_stack,
40 		TOTAL_THREADS_WAITING, STACK_SIZE);
41 K_THREAD_STACK_ARRAY_DEFINE(multiple_wake_stack,
42 		TOTAL_THREADS_WAITING, STACK_SIZE);
43 
44 
45 /******************************************************************************/
46 /* Helper functions */
condvar_isr_wake(const void * condvar)47 void condvar_isr_wake(const void *condvar)
48 {
49 	k_condvar_signal((struct k_condvar *)condvar);
50 }
51 
condvar_wake_from_isr(struct k_condvar * condvar)52 void condvar_wake_from_isr(struct k_condvar *condvar)
53 {
54 	irq_offload(condvar_isr_wake, (const void *)condvar);
55 }
56 
57 /* test condvar wait, no condvar wake */
condvar_wait_task(void * p1,void * p2,void * p3)58 void condvar_wait_task(void *p1, void *p2, void *p3)
59 {
60 	int32_t ret_value;
61 	k_ticks_t time_val = *(int *)p1;
62 
63 	k_condvar_init(&simple_condvar);
64 	zassert_true(time_val >= (int)K_TICKS_FOREVER,
65 		     "invalid timeout parameter");
66 
67 	k_mutex_lock(&test_mutex, K_FOREVER);
68 	ret_value = k_condvar_wait(&simple_condvar, &test_mutex, K_TICKS(time_val));
69 
70 	switch (time_val) {
71 	case K_TICKS_FOREVER:
72 		zassert_true(ret_value == 0,
73 		     "k_condvar_wait failed.");
74 		zassert_false(ret_value == 0,
75 		     "condvar wait task wakeup.");
76 		break;
77 	case 0:
78 		zassert_true(ret_value == -EAGAIN,
79 		     "k_condvar_wait failed.");
80 		break;
81 	default:
82 		zassert_true(ret_value == -EAGAIN,
83 		     "k_condvar_wait failed.: %d", ret_value);
84 		break;
85 	}
86 
87 	k_mutex_unlock(&test_mutex);
88 
89 }
90 
condvar_wake_task(void * p1,void * p2,void * p3)91 void condvar_wake_task(void *p1, void *p2, void *p3)
92 {
93 	int32_t ret_value;
94 
95 	ret_value = k_condvar_signal(&simple_condvar);
96 	zassert_equal(ret_value, 0,
97 		"k_condvar_wake failed. (%d!=%d)", ret_value, 0);
98 }
99 
condvar_wake_multiple(void * p1,void * p2,void * p3)100 void condvar_wake_multiple(void *p1, void *p2, void *p3)
101 {
102 	int32_t ret_value;
103 	int woken_num = *(int *)p1;
104 
105 	ret_value = k_condvar_broadcast(&simple_condvar);
106 	zassert_true(ret_value == woken_num,
107 		"k_condvar_wake failed. (%d!=%d)", ret_value, woken_num);
108 }
109 
condvar_wait_wake_task(void * p1,void * p2,void * p3)110 void condvar_wait_wake_task(void *p1, void *p2, void *p3)
111 {
112 	int32_t ret_value;
113 	int time_val = *(int *)p1;
114 
115 	zassert_true(time_val >= (int)K_TICKS_FOREVER, "invalid timeout parameter");
116 	k_mutex_lock(&test_mutex, K_FOREVER);
117 	ret_value = k_condvar_wait(&simple_condvar, &test_mutex, K_TICKS(time_val));
118 
119 	switch (time_val) {
120 	case K_TICKS_FOREVER:
121 		zassert_true(ret_value == 0,
122 		     "k_condvar_wait failed.");
123 		break;
124 	case 0:
125 		zassert_true(ret_value == -EAGAIN,
126 		     "k_condvar_wait failed.");
127 		break;
128 	default:
129 		zassert_true(ret_value == 0,
130 		     "k_condvar_wait failed.");
131 		break;
132 	}
133 
134 	k_mutex_unlock(&test_mutex);
135 }
136 /**
137  * @defgroup kernel_condvar_tests Condition Variables
138  * @ingroup all_tests
139  * @{
140  * @}
141  *
142  * @addtogroup kernel_condvar_tests
143  * @{
144  */
145 /**
146  * @brief Test k_condvar_wait() and k_condvar_wake()
147  */
ZTEST_USER(condvar_tests,test_condvar_wait_forever_wake)148 ZTEST_USER(condvar_tests, test_condvar_wait_forever_wake)
149 {
150 	woken = 1;
151 	timeout = K_TICKS_FOREVER;
152 
153 	k_condvar_init(&simple_condvar);
154 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
155 			condvar_wait_wake_task, &timeout, NULL, NULL,
156 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
157 
158 	/* giving time for the condvar_wait_wake_task to execute */
159 	k_yield();
160 
161 	k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
162 			condvar_wake_task, &woken, NULL, NULL,
163 			PRIO_WAKE, K_USER | K_INHERIT_PERMS, K_MSEC(1));
164 
165 	/* giving time for the condvar_wake_task
166 	 * and condvar_wait_wake_task to execute
167 	 */
168 	k_yield();
169 
170 	k_thread_abort(&condvar_wake_tid);
171 	k_thread_abort(&condvar_tid);
172 }
173 
174 /**
175  * @brief Test k_condvar_wait() and k_condvar_wake() with timeout
176  */
ZTEST_USER(condvar_tests,test_condvar_wait_timeout_wake)177 ZTEST_USER(condvar_tests, test_condvar_wait_timeout_wake)
178 {
179 	woken = 1;
180 	timeout = k_ms_to_ticks_ceil32(100);
181 
182 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
183 			condvar_wait_wake_task, &timeout, NULL, NULL,
184 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
185 
186 	/* giving time for the condvar_wait_wake_task to execute */
187 	k_yield();
188 
189 	k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
190 			condvar_wake_task, &woken, NULL, NULL,
191 			PRIO_WAKE, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
192 
193 	/*
194 	 * giving time for the condvar_wake_task
195 	 * and condvar_wait_wake_task to execute
196 	 */
197 	k_yield();
198 
199 
200 	k_thread_abort(&condvar_wake_tid);
201 	k_thread_abort(&condvar_tid);
202 }
203 
204 /**
205  * @brief Test k_condvar_wait() and k_condvar_wake() with timeout
206  */
ZTEST_USER(condvar_tests,test_condvar_wait_timeout)207 ZTEST_USER(condvar_tests, test_condvar_wait_timeout)
208 {
209 	timeout = k_ms_to_ticks_ceil32(50);
210 
211 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
212 			condvar_wait_task, &timeout, NULL, NULL,
213 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
214 
215 	/* giving time for the condvar_wait_task to execute */
216 	k_sleep(K_MSEC(100));
217 
218 	k_thread_abort(&condvar_tid);
219 }
220 
221 
222 /**
223  * @brief Test k_condvar_wait() forever
224  */
ZTEST_USER(condvar_tests,test_condvar_wait_forever)225 ZTEST_USER(condvar_tests, test_condvar_wait_forever)
226 {
227 	timeout = K_TICKS_FOREVER;
228 
229 
230 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
231 			condvar_wait_task, &timeout, NULL, NULL,
232 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
233 
234 	/* giving time for the condvar_wait_task to execute */
235 	k_yield();
236 
237 	k_thread_abort(&condvar_tid);
238 }
239 
240 /**
241  * @brief Test k_condvar_wait() with no wait
242  */
ZTEST_USER(condvar_tests,test_condvar_wait_nowait)243 ZTEST_USER(condvar_tests, test_condvar_wait_nowait)
244 {
245 	timeout = 0;
246 
247 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
248 			condvar_wait_task, &timeout, NULL, NULL,
249 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
250 
251 	/* giving time for the condvar_wait_task to execute */
252 	k_sleep(K_MSEC(100));
253 
254 	k_thread_abort(&condvar_tid);
255 }
256 
257 
258 /**
259  * @brief Test case for conditional variable wait and wake functionality.
260  *
261  * This test validates the behavior of conditional variables when a thread
262  * waits on a condition and another thread wakes it up.
263  */
ZTEST_USER(condvar_tests,test_condvar_wait_nowait_wake)264 ZTEST_USER(condvar_tests, test_condvar_wait_nowait_wake)
265 {
266 	woken = 0;
267 	timeout = 0;
268 
269 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
270 			condvar_wait_wake_task, &timeout, NULL, NULL,
271 			PRIO_WAIT, K_USER | K_INHERIT_PERMS,
272 			K_NO_WAIT);
273 
274 	/* giving time for the condvar_wait_wake_task to execute */
275 	k_sleep(K_MSEC(100));
276 
277 	k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
278 			condvar_wake_task, &woken, NULL, NULL,
279 			PRIO_WAKE, K_USER | K_INHERIT_PERMS,
280 			K_NO_WAIT);
281 
282 	/* giving time for the condvar_wake_task to execute */
283 	k_yield();
284 
285 	k_thread_abort(&condvar_wake_tid);
286 	k_thread_abort(&condvar_tid);
287 }
288 
289 
290 /**
291  * @brief Test case for condition variable wait and wake functionality.
292  *
293  * This test verifies the behavior of a thread waiting on a condition variable
294  * with an infinite timeout and being woken up from an interrupt service routine (ISR).
295  *
296  */
ZTEST(condvar_tests,test_condvar_wait_forever_wake_from_isr)297 ZTEST(condvar_tests, test_condvar_wait_forever_wake_from_isr)
298 {
299 	timeout = K_TICKS_FOREVER;
300 
301 	k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
302 			condvar_wait_wake_task, &timeout, NULL, NULL,
303 			PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
304 
305 	/* giving time for the condvar_wait_wake_task to execute */
306 	k_yield();
307 
308 	condvar_wake_from_isr(&simple_condvar);
309 
310 	/* giving time for the condvar_wait_wake_task to execute */
311 	k_yield();
312 
313 	k_thread_abort(&condvar_tid);
314 }
315 
316 /**
317  * @brief Test case for multiple threads waiting and waking on a condition variable.
318  *
319  * This test initializes a condition variable and creates multiple threads that
320  * wait on the condition variable. Another thread is created to wake up the
321  * waiting threads. The test ensures proper synchronization and behavior of
322  * threads waiting and waking on the condition variable.
323 
324  */
ZTEST_USER(condvar_tests,test_condvar_multiple_threads_wait_wake)325 ZTEST_USER(condvar_tests, test_condvar_multiple_threads_wait_wake)
326 {
327 	timeout = K_TICKS_FOREVER;
328 	woken = TOTAL_THREADS_WAITING;
329 
330 	k_condvar_init(&simple_condvar);
331 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
332 
333 		k_thread_create(&multiple_tid[i], multiple_stack[i],
334 				STACK_SIZE, condvar_wait_wake_task,
335 				&timeout, NULL, NULL,
336 				PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
337 	}
338 
339 	/* giving time for the other threads to execute */
340 	k_yield();
341 
342 	k_thread_create(&condvar_wake_tid, condvar_wake_stack,
343 			STACK_SIZE, condvar_wake_multiple, &woken,
344 			NULL, NULL, PRIO_WAKE,
345 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
346 
347 	/* giving time for the other threads to execute */
348 	k_yield();
349 
350 	k_thread_abort(&condvar_wake_tid);
351 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
352 		k_thread_abort(&multiple_tid[i]);
353 	}
354 }
355 
356 
condvar_multiple_wait_wake_task(void * p1,void * p2,void * p3)357 void condvar_multiple_wait_wake_task(void *p1, void *p2, void *p3)
358 {
359 	int32_t ret_value;
360 	int time_val = *(int *)p1;
361 	int idx = *(int *)p2;
362 
363 	k_condvar_init(&multiple_condvar[idx]);
364 
365 	zassert_true(time_val == (int)K_TICKS_FOREVER, "invalid timeout parameter");
366 	k_mutex_lock(&test_mutex, K_FOREVER);
367 
368 	ret_value = k_condvar_wait(&multiple_condvar[idx],
369 		&test_mutex, K_TICKS(time_val));
370 	zassert_true(ret_value == 0, "k_condvar_wait failed.");
371 
372 	k_mutex_unlock(&test_mutex);
373 }
374 
condvar_multiple_wake_task(void * p1,void * p2,void * p3)375 void condvar_multiple_wake_task(void *p1, void *p2, void *p3)
376 {
377 	int32_t ret_value;
378 	int woken_num = *(int *)p1;
379 	int idx = *(int *)p2;
380 
381 	zassert_true(woken_num > 0, "invalid woken number");
382 
383 	if (woken > 1) {
384 		ret_value = k_condvar_signal(&multiple_condvar[idx]);
385 	} else {
386 		ret_value = k_condvar_broadcast(&multiple_condvar[idx]);
387 	}
388 
389 	zassert_true(ret_value == woken_num, "k_condvar_wake failed. (%d!=%d)",
390 		     ret_value, woken_num);
391 }
392 
393 
394 /**
395  * @brief Test multiple threads waiting and waking on a condition variable.
396  *
397  * This test creates multiple threads that wait on a condition variable and
398  * another set of threads that wake them up. It ensures that the condition
399  * variable mechanism works correctly when multiple threads are involved.
400 
401  */
ZTEST_USER(condvar_tests,test_multiple_condvar_wait_wake)402 ZTEST_USER(condvar_tests, test_multiple_condvar_wait_wake)
403 {
404 	woken = 1;
405 	timeout = K_TICKS_FOREVER;
406 
407 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
408 		index[i] = i;
409 
410 		k_thread_create(&multiple_tid[i], multiple_stack[i],
411 				STACK_SIZE, condvar_multiple_wait_wake_task,
412 				&timeout, &index[i], NULL, PRIO_WAIT,
413 				K_USER | K_INHERIT_PERMS, K_NO_WAIT);
414 	}
415 
416 	/* giving time for the other threads to execute */
417 	k_msleep(10);
418 
419 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
420 		k_thread_create(&multiple_wake_tid[i], multiple_wake_stack[i],
421 				STACK_SIZE, condvar_multiple_wake_task,
422 				&woken, &index[i], NULL, PRIO_WAKE,
423 				K_USER | K_INHERIT_PERMS, K_NO_WAIT);
424 	}
425 
426 	/* giving time for the other threads to execute */
427 	k_yield();
428 
429 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
430 		;
431 	}
432 
433 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
434 		k_thread_abort(&multiple_tid[i]);
435 		k_thread_abort(&multiple_wake_tid[i]);
436 	}
437 }
438 
439 #ifdef CONFIG_USERSPACE
cond_init_null(void * p1,void * p2,void * p3)440 static void cond_init_null(void *p1, void *p2, void *p3)
441 {
442 	ARG_UNUSED(p1);
443 	ARG_UNUSED(p2);
444 	ARG_UNUSED(p3);
445 
446 	ztest_set_fault_valid(true);
447 	k_condvar_init(NULL);
448 
449 	/* should not go here*/
450 	ztest_test_fail();
451 }
452 
453 
454 /**
455  * @brief Test case for conditional variable initialization with a null parameter.
456  *
457  * This test verifies the behavior of the conditional variable initialization
458  * when a null parameter is passed. It creates a thread to execute the
459  * `cond_init_null` function and ensures the thread completes execution.
460  */
ZTEST_USER(condvar_tests,test_condvar_init_null)461 ZTEST_USER(condvar_tests, test_condvar_init_null)
462 {
463 	k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
464 			cond_init_null,
465 			NULL, NULL, NULL,
466 			K_PRIO_PREEMPT(0),
467 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
468 
469 	k_thread_join(tid, K_FOREVER);
470 }
471 #else
ZTEST_USER(condvar_tests,test_condvar_init_null)472 ZTEST_USER(condvar_tests, test_condvar_init_null)
473 {
474 	ztest_test_skip();
475 }
476 #endif
477 
478 #ifdef CONFIG_USERSPACE
cond_signal_null(void * p1,void * p2,void * p3)479 static void cond_signal_null(void *p1, void *p2, void *p3)
480 {
481 	ARG_UNUSED(p1);
482 	ARG_UNUSED(p2);
483 	ARG_UNUSED(p3);
484 
485 	ztest_set_fault_valid(true);
486 	k_condvar_signal(NULL);
487 
488 	/* should not go here*/
489 	ztest_test_fail();
490 }
491 
cond_broadcast_null(void * p1,void * p2,void * p3)492 static void cond_broadcast_null(void *p1, void *p2, void *p3)
493 {
494 	ARG_UNUSED(p1);
495 	ARG_UNUSED(p2);
496 	ARG_UNUSED(p3);
497 
498 	ztest_set_fault_valid(true);
499 	k_condvar_broadcast(NULL);
500 
501 	/* should not go here*/
502 	ztest_test_fail();
503 }
504 
cond_wait_null(void * p1,void * p2,void * p3)505 static void cond_wait_null(void *p1, void *p2, void *p3)
506 {
507 	ARG_UNUSED(p1);
508 	ARG_UNUSED(p2);
509 	ARG_UNUSED(p3);
510 
511 	ztest_set_fault_valid(true);
512 	k_condvar_wait(NULL, NULL, K_FOREVER);
513 
514 	/* should not go here*/
515 	ztest_test_fail();
516 }
517 /**
518  * @brief Test case for signaling a condition variable with a NULL parameter.
519  *
520  * This test creates a thread that attempts to signal a condition variable
521  * with a NULL parameter. It ensures that the system handles this scenario
522  * gracefully without causing unexpected behavior or crashes.
523  */
ZTEST_USER(condvar_tests,test_condvar_signal_null)524 ZTEST_USER(condvar_tests, test_condvar_signal_null)
525 {
526 	k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
527 			cond_signal_null,
528 			NULL, NULL, NULL,
529 			K_PRIO_PREEMPT(0),
530 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
531 	k_thread_join(tid, K_FOREVER);
532 }
533 
534 /**
535  * @brief Test case for broadcasting a condition variable with a NULL parameter.
536  *
537  * This test creates a thread that attempts to broadcast a condition variable
538  * with a NULL parameter. It verifies that the system can handle this edge case
539  * correctly and does not result in undefined behavior.
540  */
ZTEST_USER(condvar_tests,test_condvar_broadcast_null)541 ZTEST_USER(condvar_tests, test_condvar_broadcast_null)
542 {
543 	k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
544 			cond_broadcast_null,
545 			NULL, NULL, NULL,
546 			K_PRIO_PREEMPT(0),
547 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
548 
549 	k_thread_join(tid, K_FOREVER);
550 }
551 
552 /**
553  * @brief Test case for waiting on a condition variable with a NULL parameter.
554  *
555  * This test creates a thread that attempts to wait on a condition variable
556  * with a NULL parameter. It ensures that the system properly handles this
557  * invalid operation and maintains stability.
558  */
ZTEST_USER(condvar_tests,test_condvar_wait_null)559 ZTEST_USER(condvar_tests, test_condvar_wait_null)
560 {
561 	k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
562 			cond_wait_null,
563 			NULL, NULL, NULL,
564 			K_PRIO_PREEMPT(0),
565 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
566 	k_thread_join(tid, K_FOREVER);
567 }
568 
569 #else
ZTEST_USER(condvar_tests,test_condvar_signal_null)570 ZTEST_USER(condvar_tests, test_condvar_signal_null)
571 {
572 	ztest_test_skip();
573 }
ZTEST_USER(condvar_tests,test_condvar_broadcast_null)574 ZTEST_USER(condvar_tests, test_condvar_broadcast_null)
575 {
576 	ztest_test_skip();
577 }
ZTEST_USER(condvar_tests,test_condvar_wait_null)578 ZTEST_USER(condvar_tests, test_condvar_wait_null)
579 {
580 	ztest_test_skip();
581 }
582 #endif
583 
584 
inc_count(void * p1,void * p2,void * p3)585 void inc_count(void *p1, void *p2, void *p3)
586 {
587 	int i;
588 	long multi = (long)p2;
589 
590 	for (i = 0; i < TCOUNT; i++) {
591 		k_mutex_lock(&test_mutex, K_FOREVER);
592 		count++;
593 
594 		if (count == COUNT_LIMIT) {
595 			if (multi) {
596 				k_condvar_broadcast(&simple_condvar);
597 			} else {
598 				k_condvar_signal(&simple_condvar);
599 			}
600 		}
601 
602 		k_mutex_unlock(&test_mutex);
603 
604 		/* Sleep so threads can alternate on mutex lock */
605 		k_sleep(K_MSEC(50));
606 	}
607 }
608 
watch_count(void * p1,void * p2,void * p3)609 void watch_count(void *p1, void *p2, void *p3)
610 {
611 	long my_id = (long)p1;
612 
613 	printk("Starting %s: thread %ld\n", __func__, my_id);
614 
615 	k_mutex_lock(&test_mutex, K_FOREVER);
616 	while (count < COUNT_LIMIT) {
617 		k_condvar_wait(&simple_condvar, &test_mutex, K_FOREVER);
618 	}
619 	count += 125;
620 	k_mutex_unlock(&test_mutex);
621 }
622 
_condvar_usecase(long multi)623 void _condvar_usecase(long multi)
624 {
625 	long t1 = 1, t2 = 2, t3 = 3;
626 	int i;
627 
628 	count = 0;
629 
630 	/* Reinit mutex to prevent affection from previous testcases */
631 	k_mutex_init(&test_mutex);
632 
633 	k_thread_create(&multiple_tid[0], multiple_stack[0], STACK_SIZE, watch_count,
634 			INT_TO_POINTER(t1), NULL, NULL, K_PRIO_PREEMPT(10),
635 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
636 
637 	k_thread_create(&multiple_tid[1], multiple_stack[1], STACK_SIZE, inc_count,
638 			INT_TO_POINTER(t2), INT_TO_POINTER(multi), NULL, K_PRIO_PREEMPT(10),
639 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
640 
641 	k_thread_create(&multiple_tid[2], multiple_stack[2], STACK_SIZE, inc_count,
642 			INT_TO_POINTER(t3), INT_TO_POINTER(multi), NULL, K_PRIO_PREEMPT(10),
643 			K_USER | K_INHERIT_PERMS, K_NO_WAIT);
644 
645 	/* Wait for all threads to complete */
646 	for (i = 0; i < 3; i++) {
647 		k_thread_join(&multiple_tid[i], K_FOREVER);
648 	}
649 
650 	zassert_equal(count, 145, "Count not equal to 145");
651 
652 }
653 
654 
655 /**
656  * @brief Test case for conditional variable use case with signal
657  *
658  * This test verifies the behavior of a conditional variable in a specific
659  * use case where a signal is used. It ensures that the conditional variable
660  * operates correctly when signaled, validating synchronization mechanisms.
661  */
ZTEST_USER(condvar_tests,test_condvar_usecase_signal)662 ZTEST_USER(condvar_tests, test_condvar_usecase_signal)
663 {
664 	_condvar_usecase(0);
665 }
666 
667 
ZTEST_USER(condvar_tests,test_condvar_usecase_broadcast)668 ZTEST_USER(condvar_tests, test_condvar_usecase_broadcast)
669 {
670 	_condvar_usecase(1);
671 }
672 
673 /*test case main entry*/
condvar_tests_setup(void)674 static void *condvar_tests_setup(void)
675 {
676 #ifdef CONFIG_USERSPACE
677 	k_thread_access_grant(k_current_get(), &test_mutex, &condvar_tid, &condvar_wake_tid,
678 				&simple_condvar, &stack_1, &condvar_wake_stack);
679 
680 	for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
681 		k_thread_access_grant(k_current_get(),
682 				      &multiple_tid[i],
683 				      &multiple_wake_tid[i],
684 				      &multiple_stack[i],
685 				      &multiple_condvar[i],
686 				      &multiple_wake_stack[i]);
687 	}
688 #endif
689 	return NULL;
690 }
691 
692 /**
693  * @}
694  */
695 
696 ZTEST_SUITE(condvar_tests, NULL, condvar_tests_setup, NULL, NULL, NULL);
697