Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions zephyr/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
if (CONFIG_SOF_BOOT_TEST)
zephyr_library_sources_ifdef(CONFIG_VIRTUAL_HEAP
vmh.c
)
zephyr_library_sources_ifdef(CONFIG_VIRTUAL_HEAP
vmh.c
)
zephyr_library_sources_ifdef(CONFIG_USERSPACE
userspace/ksem.c
)
endif()

if (CONFIG_SOF_BOOT_TEST_STANDALONE)
Expand Down
62 changes: 62 additions & 0 deletions zephyr/test/userspace/ksem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2025 Intel Corporation.
*/

#include <sof/boot_test.h>

#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG);

#define USER_STACKSIZE 2048

static struct k_thread user_thread;
static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE);
Copy link

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static thread stack user_stack is reused between test_user_thread() and test_user_thread_with_lock(). This could lead to race conditions or stack corruption if both functions are called concurrently or if the previous thread hasn't fully terminated. Consider using separate stacks or ensuring proper synchronization.

Suggested change
static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE);
static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE);
static struct k_thread user_thread2;
static K_THREAD_STACK_DEFINE(user_stack2, USER_STACKSIZE);

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are executed sequentially, no danger of racing.

K_SEM_DEFINE(user_sem, 0, 1);

static void user_function(void *p1, void *p2, void *p3)
{
__ASSERT(k_is_user_context(), "isn't user");
LOG_INF("SOF thread %s (%s)",
k_is_user_context() ? "UserSpace!" : "privileged mode.",
CONFIG_BOARD_TARGET);
}

static void user_sem_function(void *p1, void *p2, void *p3)
{
__ASSERT(k_is_user_context(), "isn't user");
LOG_INF("SOF thread %s (%s)",
k_is_user_context() ? "UserSpace!" : "privileged mode.",
CONFIG_BOARD_TARGET);
k_sem_give(&user_sem);
}

static void test_user_thread(void)
{
k_thread_create(&user_thread, user_stack, USER_STACKSIZE,
user_function, NULL, NULL, NULL,
-1, K_USER, K_MSEC(0));
k_thread_join(&user_thread, K_FOREVER);
}

static void test_user_thread_with_sem(void)
{
/* Start in 10ms to have time to grant the thread access to the semaphore */
k_thread_create(&user_thread, user_stack, USER_STACKSIZE,
user_sem_function, NULL, NULL, NULL,
-1, K_USER, K_MSEC(10));
k_thread_access_grant(&user_thread, &user_sem);
k_sem_take(&user_sem, K_FOREVER);
k_thread_join(&user_thread, K_FOREVER);
}

ZTEST(sof_boot, user_space)
{
test_user_thread();
test_user_thread_with_sem();

ztest_test_pass();
}
Loading