Fix thread function signatures to avoid stack corruption on thread exit. Signed-off-by: Benedikt Schmidt <benedikt.schmidt@embedded-solutions.at>
608 lines
14 KiB
C
608 lines
14 KiB
C
/*
|
|
* Copyright (c) 2020 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
|
|
#include <zephyr/ztest.h>
|
|
#include <zephyr/irq_offload.h>
|
|
#include <zephyr/ztest_error_hook.h>
|
|
|
|
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
|
|
|
|
#define PRIO_WAIT (CONFIG_ZTEST_THREAD_PRIORITY)
|
|
#define PRIO_WAKE (CONFIG_ZTEST_THREAD_PRIORITY)
|
|
|
|
K_THREAD_STACK_DEFINE(stack_1, STACK_SIZE);
|
|
K_THREAD_STACK_DEFINE(condvar_wake_stack, STACK_SIZE);
|
|
|
|
struct k_thread condvar_tid;
|
|
struct k_thread condvar_wake_tid;
|
|
|
|
struct k_condvar simple_condvar;
|
|
K_MUTEX_DEFINE(test_mutex);
|
|
|
|
#define TOTAL_THREADS_WAITING (3)
|
|
#define TCOUNT 10
|
|
#define COUNT_LIMIT 12
|
|
|
|
ZTEST_BMEM int woken;
|
|
ZTEST_BMEM int timeout;
|
|
ZTEST_BMEM int index[TOTAL_THREADS_WAITING];
|
|
ZTEST_BMEM int count;
|
|
|
|
struct k_condvar multiple_condvar[TOTAL_THREADS_WAITING];
|
|
|
|
struct k_thread multiple_tid[TOTAL_THREADS_WAITING];
|
|
struct k_thread multiple_wake_tid[TOTAL_THREADS_WAITING];
|
|
K_THREAD_STACK_ARRAY_DEFINE(multiple_stack,
|
|
TOTAL_THREADS_WAITING, STACK_SIZE);
|
|
K_THREAD_STACK_ARRAY_DEFINE(multiple_wake_stack,
|
|
TOTAL_THREADS_WAITING, STACK_SIZE);
|
|
|
|
|
|
/******************************************************************************/
|
|
/* Helper functions */
|
|
void condvar_isr_wake(const void *condvar)
|
|
{
|
|
k_condvar_signal((struct k_condvar *)condvar);
|
|
}
|
|
|
|
void condvar_wake_from_isr(struct k_condvar *condvar)
|
|
{
|
|
irq_offload(condvar_isr_wake, (const void *)condvar);
|
|
}
|
|
|
|
/* test condvar wait, no condvar wake */
|
|
void condvar_wait_task(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
k_ticks_t time_val = *(int *)p1;
|
|
|
|
k_condvar_init(&simple_condvar);
|
|
zassert_true(time_val >= (int)K_TICKS_FOREVER,
|
|
"invalid timeout parameter");
|
|
|
|
k_mutex_lock(&test_mutex, K_FOREVER);
|
|
ret_value = k_condvar_wait(&simple_condvar, &test_mutex, K_TICKS(time_val));
|
|
|
|
switch (time_val) {
|
|
case K_TICKS_FOREVER:
|
|
zassert_true(ret_value == 0,
|
|
"k_condvar_wait failed.");
|
|
zassert_false(ret_value == 0,
|
|
"condvar wait task wakeup.");
|
|
break;
|
|
case 0:
|
|
zassert_true(ret_value == -EAGAIN,
|
|
"k_condvar_wait failed.");
|
|
break;
|
|
default:
|
|
zassert_true(ret_value == -EAGAIN,
|
|
"k_condvar_wait failed.: %d", ret_value);
|
|
break;
|
|
}
|
|
|
|
k_mutex_unlock(&test_mutex);
|
|
|
|
}
|
|
|
|
void condvar_wake_task(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
|
|
ret_value = k_condvar_signal(&simple_condvar);
|
|
zassert_equal(ret_value, 0,
|
|
"k_condvar_wake failed. (%d!=%d)", ret_value, 0);
|
|
}
|
|
|
|
void condvar_wake_multiple(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
int woken_num = *(int *)p1;
|
|
|
|
ret_value = k_condvar_broadcast(&simple_condvar);
|
|
zassert_true(ret_value == woken_num,
|
|
"k_condvar_wake failed. (%d!=%d)", ret_value, woken_num);
|
|
}
|
|
|
|
void condvar_wait_wake_task(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
int time_val = *(int *)p1;
|
|
|
|
zassert_true(time_val >= (int)K_TICKS_FOREVER, "invalid timeout parameter");
|
|
k_mutex_lock(&test_mutex, K_FOREVER);
|
|
ret_value = k_condvar_wait(&simple_condvar, &test_mutex, K_TICKS(time_val));
|
|
|
|
switch (time_val) {
|
|
case K_TICKS_FOREVER:
|
|
zassert_true(ret_value == 0,
|
|
"k_condvar_wait failed.");
|
|
break;
|
|
case 0:
|
|
zassert_true(ret_value == -EAGAIN,
|
|
"k_condvar_wait failed.");
|
|
break;
|
|
default:
|
|
zassert_true(ret_value == 0,
|
|
"k_condvar_wait failed.");
|
|
break;
|
|
}
|
|
|
|
k_mutex_unlock(&test_mutex);
|
|
}
|
|
|
|
/**
|
|
* @brief Test k_condvar_wait() and k_condvar_wake()
|
|
*/
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_forever_wake)
|
|
{
|
|
woken = 1;
|
|
timeout = K_TICKS_FOREVER;
|
|
|
|
k_condvar_init(&simple_condvar);
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_wake_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_wake_task to execute */
|
|
k_yield();
|
|
|
|
k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
|
|
condvar_wake_task, &woken, NULL, NULL,
|
|
PRIO_WAKE, K_USER | K_INHERIT_PERMS, K_MSEC(1));
|
|
|
|
/* giving time for the condvar_wake_task
|
|
* and condvar_wait_wake_task to execute
|
|
*/
|
|
k_yield();
|
|
|
|
k_thread_abort(&condvar_wake_tid);
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_timeout_wake)
|
|
{
|
|
woken = 1;
|
|
timeout = k_ms_to_ticks_ceil32(100);
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_wake_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_wake_task to execute */
|
|
k_yield();
|
|
|
|
k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
|
|
condvar_wake_task, &woken, NULL, NULL,
|
|
PRIO_WAKE, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/*
|
|
* giving time for the condvar_wake_task
|
|
* and condvar_wait_wake_task to execute
|
|
*/
|
|
k_yield();
|
|
|
|
|
|
k_thread_abort(&condvar_wake_tid);
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_timeout)
|
|
{
|
|
timeout = k_ms_to_ticks_ceil32(50);
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_task to execute */
|
|
k_sleep(K_MSEC(100));
|
|
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Test k_condvar_wait() forever
|
|
*/
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_forever)
|
|
{
|
|
timeout = K_TICKS_FOREVER;
|
|
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_task to execute */
|
|
k_yield();
|
|
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_nowait)
|
|
{
|
|
timeout = 0;
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_task to execute */
|
|
k_sleep(K_MSEC(100));
|
|
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_nowait_wake)
|
|
{
|
|
woken = 0;
|
|
timeout = 0;
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_wake_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS,
|
|
K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_wake_task to execute */
|
|
k_sleep(K_MSEC(100));
|
|
|
|
k_thread_create(&condvar_wake_tid, condvar_wake_stack, STACK_SIZE,
|
|
condvar_wake_task, &woken, NULL, NULL,
|
|
PRIO_WAKE, K_USER | K_INHERIT_PERMS,
|
|
K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wake_task to execute */
|
|
k_yield();
|
|
|
|
k_thread_abort(&condvar_wake_tid);
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
|
|
ZTEST(condvar_tests, test_condvar_wait_forever_wake_from_isr)
|
|
{
|
|
timeout = K_TICKS_FOREVER;
|
|
|
|
k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
condvar_wait_wake_task, &timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the condvar_wait_wake_task to execute */
|
|
k_yield();
|
|
|
|
condvar_wake_from_isr(&simple_condvar);
|
|
|
|
/* giving time for the condvar_wait_wake_task to execute */
|
|
k_yield();
|
|
|
|
k_thread_abort(&condvar_tid);
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_multiple_threads_wait_wake)
|
|
{
|
|
timeout = K_TICKS_FOREVER;
|
|
woken = TOTAL_THREADS_WAITING;
|
|
|
|
k_condvar_init(&simple_condvar);
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
|
|
k_thread_create(&multiple_tid[i], multiple_stack[i],
|
|
STACK_SIZE, condvar_wait_wake_task,
|
|
&timeout, NULL, NULL,
|
|
PRIO_WAIT, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
}
|
|
|
|
/* giving time for the other threads to execute */
|
|
k_yield();
|
|
|
|
k_thread_create(&condvar_wake_tid, condvar_wake_stack,
|
|
STACK_SIZE, condvar_wake_multiple, &woken,
|
|
NULL, NULL, PRIO_WAKE,
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* giving time for the other threads to execute */
|
|
k_yield();
|
|
|
|
k_thread_abort(&condvar_wake_tid);
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
k_thread_abort(&multiple_tid[i]);
|
|
}
|
|
}
|
|
|
|
|
|
void condvar_multiple_wait_wake_task(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
int time_val = *(int *)p1;
|
|
int idx = *(int *)p2;
|
|
|
|
k_condvar_init(&multiple_condvar[idx]);
|
|
|
|
zassert_true(time_val == (int)K_TICKS_FOREVER, "invalid timeout parameter");
|
|
k_mutex_lock(&test_mutex, K_FOREVER);
|
|
|
|
ret_value = k_condvar_wait(&multiple_condvar[idx],
|
|
&test_mutex, K_TICKS(time_val));
|
|
zassert_true(ret_value == 0, "k_condvar_wait failed.");
|
|
|
|
k_mutex_unlock(&test_mutex);
|
|
}
|
|
|
|
void condvar_multiple_wake_task(void *p1, void *p2, void *p3)
|
|
{
|
|
int32_t ret_value;
|
|
int woken_num = *(int *)p1;
|
|
int idx = *(int *)p2;
|
|
|
|
zassert_true(woken_num > 0, "invalid woken number");
|
|
|
|
if (woken > 1) {
|
|
ret_value = k_condvar_signal(&multiple_condvar[idx]);
|
|
} else {
|
|
ret_value = k_condvar_broadcast(&multiple_condvar[idx]);
|
|
}
|
|
|
|
zassert_true(ret_value == woken_num, "k_condvar_wake failed. (%d!=%d)",
|
|
ret_value, woken_num);
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_multiple_condvar_wait_wake)
|
|
{
|
|
woken = 1;
|
|
timeout = K_TICKS_FOREVER;
|
|
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
index[i] = i;
|
|
|
|
k_thread_create(&multiple_tid[i], multiple_stack[i],
|
|
STACK_SIZE, condvar_multiple_wait_wake_task,
|
|
&timeout, &index[i], NULL, PRIO_WAIT,
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
}
|
|
|
|
/* giving time for the other threads to execute */
|
|
k_msleep(10);
|
|
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
k_thread_create(&multiple_wake_tid[i], multiple_wake_stack[i],
|
|
STACK_SIZE, condvar_multiple_wake_task,
|
|
&woken, &index[i], NULL, PRIO_WAKE,
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
}
|
|
|
|
/* giving time for the other threads to execute */
|
|
k_yield();
|
|
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
;
|
|
}
|
|
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
k_thread_abort(&multiple_tid[i]);
|
|
k_thread_abort(&multiple_wake_tid[i]);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
static void cond_init_null(void *p1, void *p2, void *p3)
|
|
{
|
|
ARG_UNUSED(p1);
|
|
ARG_UNUSED(p2);
|
|
ARG_UNUSED(p3);
|
|
|
|
ztest_set_fault_valid(true);
|
|
k_condvar_init(NULL);
|
|
|
|
/* should not go here*/
|
|
ztest_test_fail();
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_init_null)
|
|
{
|
|
k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
cond_init_null,
|
|
NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
k_thread_join(tid, K_FOREVER);
|
|
}
|
|
#else
|
|
ZTEST_USER(condvar_tests, test_condvar_init_null)
|
|
{
|
|
ztest_test_skip();
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
static void cond_signal_null(void *p1, void *p2, void *p3)
|
|
{
|
|
ARG_UNUSED(p1);
|
|
ARG_UNUSED(p2);
|
|
ARG_UNUSED(p3);
|
|
|
|
ztest_set_fault_valid(true);
|
|
k_condvar_signal(NULL);
|
|
|
|
/* should not go here*/
|
|
ztest_test_fail();
|
|
}
|
|
|
|
static void cond_broadcast_null(void *p1, void *p2, void *p3)
|
|
{
|
|
ARG_UNUSED(p1);
|
|
ARG_UNUSED(p2);
|
|
ARG_UNUSED(p3);
|
|
|
|
ztest_set_fault_valid(true);
|
|
k_condvar_broadcast(NULL);
|
|
|
|
/* should not go here*/
|
|
ztest_test_fail();
|
|
}
|
|
|
|
static void cond_wait_null(void *p1, void *p2, void *p3)
|
|
{
|
|
ARG_UNUSED(p1);
|
|
ARG_UNUSED(p2);
|
|
ARG_UNUSED(p3);
|
|
|
|
ztest_set_fault_valid(true);
|
|
k_condvar_wait(NULL, NULL, K_FOREVER);
|
|
|
|
/* should not go here*/
|
|
ztest_test_fail();
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_signal_null)
|
|
{
|
|
k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
cond_signal_null,
|
|
NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
k_thread_join(tid, K_FOREVER);
|
|
}
|
|
ZTEST_USER(condvar_tests, test_condvar_broadcast_null)
|
|
{
|
|
k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
cond_broadcast_null,
|
|
NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
k_thread_join(tid, K_FOREVER);
|
|
}
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_null)
|
|
{
|
|
k_tid_t tid = k_thread_create(&condvar_tid, stack_1, STACK_SIZE,
|
|
cond_wait_null,
|
|
NULL, NULL, NULL,
|
|
K_PRIO_PREEMPT(0),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
k_thread_join(tid, K_FOREVER);
|
|
}
|
|
|
|
#else
|
|
ZTEST_USER(condvar_tests, test_condvar_signal_null)
|
|
{
|
|
ztest_test_skip();
|
|
}
|
|
ZTEST_USER(condvar_tests, test_condvar_broadcast_null)
|
|
{
|
|
ztest_test_skip();
|
|
}
|
|
ZTEST_USER(condvar_tests, test_condvar_wait_null)
|
|
{
|
|
ztest_test_skip();
|
|
}
|
|
#endif
|
|
|
|
|
|
void inc_count(void *p1, void *p2, void *p3)
|
|
{
|
|
int i;
|
|
long multi = (long)p2;
|
|
|
|
for (i = 0; i < TCOUNT; i++) {
|
|
k_mutex_lock(&test_mutex, K_FOREVER);
|
|
count++;
|
|
|
|
if (count == COUNT_LIMIT) {
|
|
if (multi) {
|
|
k_condvar_broadcast(&simple_condvar);
|
|
} else {
|
|
k_condvar_signal(&simple_condvar);
|
|
}
|
|
}
|
|
|
|
k_mutex_unlock(&test_mutex);
|
|
|
|
/* Sleep so threads can alternate on mutex lock */
|
|
k_sleep(K_MSEC(50));
|
|
}
|
|
}
|
|
|
|
void watch_count(void *p1, void *p2, void *p3)
|
|
{
|
|
long my_id = (long)p1;
|
|
|
|
printk("Starting %s: thread %ld\n", __func__, my_id);
|
|
|
|
k_mutex_lock(&test_mutex, K_FOREVER);
|
|
while (count < COUNT_LIMIT) {
|
|
k_condvar_wait(&simple_condvar, &test_mutex, K_FOREVER);
|
|
}
|
|
count += 125;
|
|
k_mutex_unlock(&test_mutex);
|
|
}
|
|
|
|
void _condvar_usecase(long multi)
|
|
{
|
|
long t1 = 1, t2 = 2, t3 = 3;
|
|
int i;
|
|
|
|
count = 0;
|
|
|
|
/* Reinit mutex to prevent affection from previous testcases */
|
|
k_mutex_init(&test_mutex);
|
|
|
|
k_thread_create(&multiple_tid[0], multiple_stack[0], STACK_SIZE, watch_count,
|
|
INT_TO_POINTER(t1), NULL, NULL, K_PRIO_PREEMPT(10),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
k_thread_create(&multiple_tid[1], multiple_stack[1], STACK_SIZE, inc_count,
|
|
INT_TO_POINTER(t2), INT_TO_POINTER(multi), NULL, K_PRIO_PREEMPT(10),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
k_thread_create(&multiple_tid[2], multiple_stack[2], STACK_SIZE, inc_count,
|
|
INT_TO_POINTER(t3), INT_TO_POINTER(multi), NULL, K_PRIO_PREEMPT(10),
|
|
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
|
|
|
/* Wait for all threads to complete */
|
|
for (i = 0; i < 3; i++) {
|
|
k_thread_join(&multiple_tid[i], K_FOREVER);
|
|
}
|
|
|
|
zassert_equal(count, 145, "Count not equal to 145");
|
|
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_usecase_signal)
|
|
{
|
|
_condvar_usecase(0);
|
|
}
|
|
|
|
ZTEST_USER(condvar_tests, test_condvar_usecase_broadcast)
|
|
{
|
|
_condvar_usecase(1);
|
|
}
|
|
|
|
/*test case main entry*/
|
|
static void *condvar_tests_setup(void)
|
|
{
|
|
#ifdef CONFIG_USERSPACE
|
|
k_thread_access_grant(k_current_get(), &test_mutex, &condvar_tid, &condvar_wake_tid,
|
|
&simple_condvar, &stack_1, &condvar_wake_stack);
|
|
|
|
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
|
|
k_thread_access_grant(k_current_get(),
|
|
&multiple_tid[i],
|
|
&multiple_wake_tid[i],
|
|
&multiple_stack[i],
|
|
&multiple_condvar[i],
|
|
&multiple_wake_stack[i]);
|
|
}
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
ZTEST_SUITE(condvar_tests, NULL, condvar_tests_setup, NULL, NULL, NULL);
|