/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include "test_sched.h" #include #include #include #include struct k_thread user_thread; K_SEM_DEFINE(user_sem, 0, 1); ZTEST_BMEM volatile int thread_was_preempt; #define THREAD_TEST_PRIORITY 0 K_THREAD_STACK_DEFINE(ustack, STACK_SIZE); static void sleepy_thread(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); k_sleep(K_FOREVER); k_sem_give(&user_sem); } ZTEST_USER(threads_scheduling, test_user_k_wakeup) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, sleepy_thread, NULL, NULL, NULL, k_thread_priority_get(k_current_get()), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_yield(); /* Let thread run and start sleeping forever */ k_wakeup(&user_thread); k_sem_take(&user_sem, K_FOREVER); k_thread_abort(tid); } static void preempt_test_thread(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); thread_was_preempt = k_is_preempt_thread(); k_sem_give(&user_sem); } ZTEST_USER(threads_scheduling, test_user_k_is_preempt) { /* thread_was_preempt is volatile, and static analysis doesn't * like to see it being tested inside zassert_true, because * the read is treated as a "side effect" of an assertion * (e.g. a read is significant for things like volatile MMIO * addresses, and assertions may or may not be compiled, even * though here in a test they always will be and in any case * the value is a static variable above marked volatile for * threadsafety). Read it into a local variable first to * evade the warning. */ int twp; k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, preempt_test_thread, NULL, NULL, NULL, k_thread_priority_get(k_current_get()), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_sem_take(&user_sem, K_FOREVER); twp = thread_was_preempt; zassert_false(twp, "unexpected return value"); k_thread_abort(tid); tid = k_thread_create(&user_thread, ustack, STACK_SIZE, preempt_test_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(1), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_sem_take(&user_sem, K_FOREVER); twp = thread_was_preempt; zassert_true(twp, "unexpected return value"); k_thread_abort(tid); } /** * userspace negative test: take NULL as input param to verify * the api will trigger a fatal exception */ #ifdef CONFIG_USERSPACE static void thread_suspend_init_null(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); k_thread_suspend(NULL); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_suspend() API * * @details Create a thread and set k_thread_suspend() input param to NULL * will trigger a fatal error. * * @ingroup kernel_sched_tests * * @see k_thread_suspend() */ ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_suspend_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_suspend_init_null) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_resume_init_null(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); k_thread_resume(NULL); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_resume() API * * @details Create a thread and set k_thread_resume() input param to NULL * will trigger a fatal error. * * @ingroup kernel_sched_tests * * @see k_thread_resume() */ ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_resume_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_resume_init_null) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_priority_get_init_null(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); k_thread_priority_get(NULL); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_priority_get() API * * @details Create a thread and set thread_k_thread_priority_get() param input to * NULL will trigger a fatal error. * * @ingroup kernel_sched_tests * * @see thread_k_thread_priority_get() */ ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_priority_get_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_priority_get_init_null) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_priority_set_init_null(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); k_thread_priority_set(NULL, 0); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_priority_set() API * * @details Create a thread and set k_thread_priority_set() param input to * NULL will trigger a fatal error. * * @ingroup kernel_sched_tests * * @see k_thread_priority_set() */ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_priority_set_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_priority_set_init_null) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_priority_set_overmax(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); /* set valid priority value outside the priority range will invoke fatal error */ k_thread_priority_set(k_current_get(), K_LOWEST_APPLICATION_THREAD_PRIO + 1); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_priority_set() API * * @details Check input param range overmax in userspace test. * * @ingroup kernel_sched_tests * * @see k_thread_priority_set() */ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_priority_set_overmax, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_priority_set_overmax) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_priority_set_upgrade(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); /* at first, set an valid priority */ k_thread_priority_set(k_current_get(), THREAD_TEST_PRIORITY); /* it cannot upgraded thread priority in usermode */ k_thread_priority_set(k_current_get(), THREAD_TEST_PRIORITY - 1); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_thread_priority_set() API * * @details Check input param range fail in userspace test. * * @ingroup kernel_sched_tests * * @see k_thread_priority_set() */ ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_priority_set_upgrade, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_thread_priority_set_upgrade) { ztest_test_skip(); } #endif #ifdef CONFIG_USERSPACE static void thread_wakeup_init_null(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); ztest_set_fault_valid(true); k_wakeup(NULL); /* should not go here */ ztest_test_fail(); } /** * @brief Test k_wakeup() API * * @details Create a thread and set k_wakeup() input param to NULL * will trigger a fatal error * * @ingroup kernel_sched_tests * * @see k_wakeup() */ ZTEST_USER(threads_scheduling, test_k_wakeup_init_null) { k_tid_t tid = k_thread_create(&user_thread, ustack, STACK_SIZE, thread_wakeup_init_null, NULL, NULL, NULL, K_PRIO_PREEMPT(THREAD_TEST_PRIORITY), K_USER | K_INHERIT_PERMS, K_NO_WAIT); k_thread_join(tid, K_FOREVER); } #else ZTEST_USER(threads_scheduling, test_k_wakeup_init_null) { ztest_test_skip(); } #endif