🎯 Sync smart & scheduler codes (#8537)

Signed-off-by: Shell <smokewood@qq.com>
Co-authored-by: xqyjlj <xqyjlj@126.com>
This commit is contained in:
Shell
2024-02-23 17:49:15 +08:00
committed by GitHub
co-authored by xqyjlj
parent 6fe69d7431
commit 71560bafb5
71 changed files with 6218 additions and 2329 deletions
+4
View File
@@ -69,4 +69,8 @@ config UTEST_MTSAFE_KPRINT_TC
bool "mtsafe kprint test"
default n
config UTEST_SCHEDULER_TC
bool "scheduler test"
default n
endmenu
@@ -50,6 +50,13 @@ if GetDepend(['UTEST_HOOKLIST_TC']):
if GetDepend(['UTEST_MTSAFE_KPRINT_TC']):
src += ['mtsafe_kprint_tc.c']
# Stressful testcase for scheduler (MP/UP)
if GetDepend(['UTEST_SCHEDULER_TC']):
src += ['sched_timed_sem_tc.c']
src += ['sched_timed_mtx_tc.c']
src += ['sched_mtx_tc.c']
src += ['sched_sem_tc.c', 'sched_thread_tc.c']
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
Return('group')
+5 -4
View File
@@ -8,15 +8,16 @@
* 2021-09.01 luckyzjq the first version
* 2023-09-15 xqyjlj change stack size in cpu64
*/
#define __RT_IPC_SOURCE__
#include <rtthread.h>
#include <stdlib.h>
#include "utest.h"
#ifdef ARCH_CPU_64BIT
#define THREAD_STACKSIZE 4096
#define THREAD_STACKSIZE 8192
#else
#define THREAD_STACKSIZE 1024
#define THREAD_STACKSIZE 4096
#endif
static struct rt_mutex static_mutex;
@@ -241,7 +242,7 @@ static void static_thread1_entry(void *param)
/* thread3 hode mutex thread2 take mutex */
/* check thread2 and thread3 priority */
if (tid2->current_priority != tid3->current_priority)
if (RT_SCHED_PRIV(tid2).current_priority != RT_SCHED_PRIV(tid3).current_priority)
{
uassert_true(RT_FALSE);
}
@@ -550,7 +551,7 @@ static void dynamic_thread1_entry(void *param)
/* thread3 hode mutex thread2 take mutex */
/* check thread2 and thread3 priority */
if (tid2->current_priority != tid3->current_priority)
if (RT_SCHED_PRIV(tid2).current_priority != RT_SCHED_PRIV(tid3).current_priority)
{
uassert_true(RT_FALSE);
}
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-17 Shell the first version
*/
#include <rtthread.h>
#include <stdlib.h>
#include "utest.h"
/**
* Stressful Test for Mutex
*/
#define TEST_SECONDS 30
#define TEST_LOOP_TICKS (TEST_SECONDS * RT_TICK_PER_SECOND)
#define TEST_THREAD_COUNTS (RT_CPUS_NR)
#define TEST_PROGRESS_COUNTS (36)
#define TEST_PROGRESS_ON (TEST_LOOP_TICKS/TEST_PROGRESS_COUNTS)
#define TEST_PRIORITY_HIGHEST (UTEST_THR_PRIORITY+1)
#define TEST_RANDOM_LATENCY_MAX (1000 * 1000)
static struct rt_semaphore _thr_exit_sem;
static rt_atomic_t _progress_counter;
static rt_atomic_t _exit_flag;
static struct rt_mutex _racing_lock;
static void test_thread_entry(void *param)
{
while (1)
{
rt_mutex_take(&_racing_lock, RT_WAITING_FOREVER);
rt_mutex_release(&_racing_lock);
if (rt_atomic_load(&_exit_flag))
{
break;
}
}
rt_sem_release(&_thr_exit_sem);
}
static void mutex_stress_tc(void)
{
rt_err_t error;
rt_thread_t tester;
const rt_base_t priority_base = TEST_PRIORITY_HIGHEST;
for (size_t i = 0; i < TEST_THREAD_COUNTS; i++)
{
tester = rt_thread_create(
"tester",
test_thread_entry,
(void *)0,
UTEST_THR_STACK_SIZE,
priority_base + (i % (RT_THREAD_PRIORITY_MAX - TEST_PRIORITY_HIGHEST)),
1);
rt_thread_startup(tester);
}
for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
{
rt_thread_delay(1);
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
/* trigger exit request for all sub-threads */
rt_atomic_store(&_exit_flag, 1);
/* waiting for sub-threads to exit */
for (size_t i = 0; i < TEST_THREAD_COUNTS; i++)
{
error = rt_sem_take(&_thr_exit_sem, RT_WAITING_FOREVER);
uassert_int_equal(error, RT_EOK);
}
}
static rt_err_t utest_tc_init(void)
{
int *pseed = rt_malloc(sizeof(int));
srand(*(int *)pseed);
rt_free(pseed);
rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
rt_mutex_init(&_racing_lock, "ipc", RT_IPC_FLAG_PRIO);
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_sem_detach(&_thr_exit_sem);
rt_mutex_detach(&_racing_lock);
return RT_EOK;
}
static void testcase(void)
{
UTEST_UNIT_RUN(mutex_stress_tc);
}
UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.mutex", utest_tc_init, utest_tc_cleanup, TEST_SECONDS);
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-17 Shell the first version
*/
#define __RT_IPC_SOURCE__
#include <rtthread.h>
#include "rthw.h"
#include "utest.h"
#define KERN_TEST_CONFIG_LOOP_TIMES 160
#define KERN_TEST_CONCURRENT_THREADS (RT_CPUS_NR * 2)
#define KERN_TEST_CONFIG_HIGHEST_PRIO 3
#define KERN_TEST_CONFIG_LOWEST_PRIO (RT_THREAD_PRIORITY_MAX - 2)
#define TEST_LEVEL_COUNTS (KERN_TEST_CONFIG_LOWEST_PRIO - KERN_TEST_CONFIG_HIGHEST_PRIO + 1)
#if TEST_LEVEL_COUNTS <= RT_CPUS_NR
#warning for the best of this test, TEST_LEVEL_COUNTS should greater than RT_CPUS_NR
#endif
#if KERN_TEST_CONCURRENT_THREADS < RT_CPUS_NR
#warning for the best of this test, KERN_TEST_CONCURRENT_THREADS should greater than RT_CPUS_NR
#endif
#if KERN_TEST_CONFIG_LOWEST_PRIO >= RT_THREAD_PRIORITY_MAX - 1
#error the thread priority should at least be greater than idle
#endif
static rt_atomic_t _star_counter = 1;
static struct rt_semaphore _thr_exit_sem;
static struct rt_semaphore _level_waiting[TEST_LEVEL_COUNTS];
static rt_thread_t _thread_matrix[TEST_LEVEL_COUNTS][KERN_TEST_CONCURRENT_THREADS];
static rt_atomic_t _load_average[RT_CPUS_NR];
static void _print_char(rt_thread_t thr_self, int character)
{
rt_base_t current_counter;
#ifdef RT_USING_SMP
rt_kprintf("%c%d", character, RT_SCHED_CTX(thr_self).oncpu);
#else
rt_kprintf("%c0", character);
#endif /* RT_USING_SMP */
current_counter = rt_atomic_add(&_star_counter, 1);
if (current_counter % 30 == 0)
{
rt_kprintf("\n");
}
}
static void _stats_load_avg_inc(void)
{
int cpuid;
cpuid = rt_hw_cpu_id();
rt_atomic_add(&_load_average[cpuid], 1);
}
static void _stats_load_avg_print(void)
{
rt_base_t counts = 0;
const rt_base_t total_test_counts = KERN_TEST_CONFIG_LOOP_TIMES * TEST_LEVEL_COUNTS * KERN_TEST_CONCURRENT_THREADS;
for (size_t i = 0; i < RT_CPUS_NR; i++)
{
rt_kprintf("%ld ", _load_average[i]);
counts += _load_average[i];
}
rt_kprintf("\n");
uassert_int_equal(counts, total_test_counts);
}
static void _thread_entry(void *param)
{
int level = (rt_ubase_t)param;
rt_thread_t thr_self = rt_thread_self();
if (level == 0)
{
/* always the first to execute among other working threads */
for (size_t i = 0; i < KERN_TEST_CONFIG_LOOP_TIMES; i++)
{
/* notify our consumer */
rt_sem_release(&_level_waiting[level + 1]);
_stats_load_avg_inc();
/* waiting for resource of ours */
rt_sem_take(&_level_waiting[level], RT_WAITING_FOREVER);
}
}
else if (level == TEST_LEVEL_COUNTS - 1)
{
for (size_t i = 0; i < KERN_TEST_CONFIG_LOOP_TIMES; i++)
{
/* waiting for our resource first */
rt_sem_take(&_level_waiting[level], RT_WAITING_FOREVER);
_stats_load_avg_inc();
_print_char(thr_self, '*');
rt_thread_delay(1);
/* produce for level 0 worker */
rt_sem_release(&_level_waiting[0]);
}
}
else
{
for (size_t i = 0; i < KERN_TEST_CONFIG_LOOP_TIMES; i++)
{
/* waiting for resource of ours */
rt_sem_take(&_level_waiting[level], RT_WAITING_FOREVER);
_stats_load_avg_inc();
/* notify our consumer */
rt_sem_release(&_level_waiting[level + 1]);
}
}
uassert_true(1);
rt_sem_release(&_thr_exit_sem);
return;
}
static void scheduler_tc(void)
{
LOG_I("Test starts...");
for (size_t i = 0; i < TEST_LEVEL_COUNTS; i++)
{
for (size_t j = 0; j < KERN_TEST_CONCURRENT_THREADS; j++)
{
rt_thread_startup(_thread_matrix[i][j]);
}
}
LOG_I("%d threads startup...", TEST_LEVEL_COUNTS * KERN_TEST_CONCURRENT_THREADS);
/* waiting for sub-threads to exit */
for (size_t i = 0; i < TEST_LEVEL_COUNTS * KERN_TEST_CONCURRENT_THREADS; i++)
{
rt_sem_take(&_thr_exit_sem, RT_WAITING_FOREVER);
}
/* print load average */
_stats_load_avg_print();
}
static rt_err_t utest_tc_init(void)
{
LOG_I("Setup environment...");
rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
for (size_t i = 0; i < TEST_LEVEL_COUNTS; i++)
{
rt_sem_init(&_level_waiting[i], "test", 0, RT_IPC_FLAG_PRIO);
for (size_t j = 0; j < KERN_TEST_CONCURRENT_THREADS; j++)
{
_thread_matrix[i][j] =
rt_thread_create("test",
_thread_entry,
(void *)i,
UTEST_THR_STACK_SIZE,
KERN_TEST_CONFIG_HIGHEST_PRIO+i,
5);
if (!_thread_matrix[i][j])
uassert_not_null(_thread_matrix[i][j]);
}
}
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_sem_detach(&_thr_exit_sem);
for (size_t i = 0; i < TEST_LEVEL_COUNTS; i++)
{
rt_sem_detach(&_level_waiting[i]);
}
return RT_EOK;
}
static void testcase(void)
{
UTEST_UNIT_RUN(scheduler_tc);
}
UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.sem", utest_tc_init, utest_tc_cleanup, 10);
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-25 Shell init ver.
*/
#define __RT_KERNEL_SOURCE__
#include <rtthread.h>
#include "utest.h"
#define TEST_LOOP_TIMES (100 * 1000)
#define TEST_PROGRESS_COUNTS (36)
#define TEST_THREAD_COUNT (RT_CPUS_NR * 1)
#define TEST_PROGRESS_ON (TEST_LOOP_TIMES*TEST_THREAD_COUNT/TEST_PROGRESS_COUNTS)
static struct rt_semaphore _thr_exit_sem;
static rt_atomic_t _progress_counter;
static volatile rt_thread_t threads_group[TEST_THREAD_COUNT][2];
static void _thread_entry1(void *param)
{
rt_base_t critical_level;
size_t idx = (size_t)param;
for (size_t i = 0; i < TEST_LOOP_TIMES; i++)
{
critical_level = rt_enter_critical();
rt_thread_suspend(rt_thread_self());
rt_thread_resume(threads_group[idx][1]);
rt_exit_critical_safe(critical_level);
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void _thread_entry2(void *param)
{
rt_base_t critical_level;
size_t idx = (size_t)param;
for (size_t i = 0; i < TEST_LOOP_TIMES; i++)
{
critical_level = rt_enter_critical();
rt_thread_suspend(rt_thread_self());
rt_thread_resume(threads_group[idx][0]);
rt_exit_critical_safe(critical_level);
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void scheduler_tc(void)
{
for (size_t i = 0; i < TEST_THREAD_COUNT; i++)
{
rt_thread_t t1 =
rt_thread_create(
"t1",
_thread_entry1,
(void *)i,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
100);
rt_thread_t t2 =
rt_thread_create(
"t2",
_thread_entry2,
(void *)i,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
100);
threads_group[i][0] = t1;
threads_group[i][1] = t2;
}
for (size_t i = 0; i < TEST_THREAD_COUNT; i++)
{
rt_thread_startup(threads_group[i][0]);
rt_thread_startup(threads_group[i][1]);
}
for (size_t i = 0; i < TEST_THREAD_COUNT; i++)
{
rt_sem_take(&_thr_exit_sem, RT_WAITING_FOREVER);
}
}
static rt_err_t utest_tc_init(void)
{
rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_sem_detach(&_thr_exit_sem);
return RT_EOK;
}
static void testcase(void)
{
UTEST_UNIT_RUN(scheduler_tc);
}
UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.thread", utest_tc_init, utest_tc_cleanup, 10);
@@ -0,0 +1,232 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-25 Shell init ver.
*/
#define __RT_KERNEL_SOURCE__
#include <rtthread.h>
#include <stdlib.h>
#include "utest.h"
#define TEST_SECONDS 10
#define TEST_LOOP_TICKS (TEST_SECONDS * RT_TICK_PER_SECOND)
#define TEST_PROGRESS_COUNTS (36)
#define TEST_PROGRESS_ON (TEST_LOOP_TICKS*2/TEST_PROGRESS_COUNTS)
static struct rt_semaphore _thr_exit_sem;
static struct rt_mutex _ipc_primitive;
static struct rt_semaphore _cons_can_take_mtx;
static struct rt_semaphore _prod_can_take_mtx;
static rt_atomic_t _progress_counter;
#define CONSUMER_MAGIC 0x11223344
#define PRODUCER_MAGIC 0x44332211
static rt_atomic_t _last_holder_flag = CONSUMER_MAGIC;
static rt_base_t _timedout_failed_times = 0;
/**
* Test on timedout IPC with racing condition where timedout routine and producer
* thread may race to wakeup sleeper.
*
* This test will fork 2 thread, one producer and one consumer. The producer will
* looping and trigger the IPC on the edge of new tick arrives. The consumer will
* wait on IPC with a timedout of 1 tick.
*/
static void _wait_until_edge(void)
{
rt_tick_t entry_level, current;
rt_base_t random_latency;
entry_level = rt_tick_get();
do
{
current = rt_tick_get();
}
while (current == entry_level);
/* give a random latency for test */
random_latency = rand() % 1000 * 1000;
entry_level = current;
for (size_t i = 0; i < random_latency; i++)
{
current = rt_tick_get();
if (current != entry_level)
break;
}
}
static void _producer_entry(void *param)
{
rt_err_t error;
for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
{
/**
* only try to take mutex after consumer have taken it after last
* release from us.
*/
error = rt_sem_take(&_prod_can_take_mtx, RT_WAITING_FOREVER);
if (error)
{
uassert_true(0);
break;
}
error = rt_mutex_take(&_ipc_primitive, RT_WAITING_FOREVER);
if (error)
{
uassert_true(0);
break;
}
/* ensure that mutex should be held in round-robin method */
if (rt_atomic_load(&_last_holder_flag) != CONSUMER_MAGIC)
{
uassert_true(0);
break;
}
else
{
rt_atomic_store(&_last_holder_flag, PRODUCER_MAGIC);
rt_sem_release(&_cons_can_take_mtx);
}
_wait_until_edge();
rt_mutex_release(&_ipc_primitive);
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void _consumer_entry(void *param)
{
rt_err_t error;
for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
{
/**
* only try to take mutex after producer have taken it after last
* release from us.
*/
error = rt_sem_take(&_cons_can_take_mtx, RT_WAITING_FOREVER);
if (error)
{
uassert_true(0);
break;
}
while (1)
{
error = rt_mutex_take_interruptible(&_ipc_primitive, 1);
if (error == -RT_ETIMEOUT)
{
_timedout_failed_times++;
if (rt_mutex_get_owner(&_ipc_primitive) == rt_thread_self())
{
uassert_true(0);
break;
}
}
else
{
break;
}
}
if (error != RT_EOK)
{
uassert_true(0);
break;
}
/* ensure that mutex should be held in round-robin method */
if (rt_atomic_load(&_last_holder_flag) != PRODUCER_MAGIC)
{
uassert_true(0);
break;
}
else
{
rt_atomic_store(&_last_holder_flag, CONSUMER_MAGIC);
rt_sem_release(&_prod_can_take_mtx);
}
rt_mutex_release(&_ipc_primitive);
if (rt_mutex_get_owner(&_ipc_primitive) == rt_thread_self())
{
uassert_true(0);
break;
}
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void timed_mtx_tc(void)
{
rt_thread_t prod = rt_thread_create(
"prod",
_producer_entry,
(void *)0,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
4);
rt_thread_t cons = rt_thread_create(
"cons",
_consumer_entry,
(void *)0,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
100);
rt_thread_startup(prod);
rt_thread_startup(cons);
for (size_t i = 0; i < 2; i++)
{
uassert_int_equal(
rt_sem_take(&_thr_exit_sem, 2 * TEST_LOOP_TICKS),
RT_EOK);
}
/* Summary */
LOG_I("Total failed times: %ld(in %d)\n", _timedout_failed_times, TEST_LOOP_TICKS);
}
static rt_err_t utest_tc_init(void)
{
_timedout_failed_times = 0;
rt_mutex_init(&_ipc_primitive, "ipc", RT_IPC_FLAG_PRIO);
rt_sem_init(&_cons_can_take_mtx, "test", 0, RT_IPC_FLAG_PRIO);
rt_sem_init(&_prod_can_take_mtx, "test", 1, RT_IPC_FLAG_PRIO);
rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_mutex_detach(&_ipc_primitive);
rt_sem_detach(&_cons_can_take_mtx);
rt_sem_detach(&_prod_can_take_mtx);
rt_sem_detach(&_thr_exit_sem);
return RT_EOK;
}
static void testcase(void)
{
UTEST_UNIT_RUN(timed_mtx_tc);
}
UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.timed_mtx", utest_tc_init, utest_tc_cleanup, TEST_SECONDS * 2);
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-01-25 Shell init ver.
*/
#define __RT_KERNEL_SOURCE__
#include <rtthread.h>
#include <stdlib.h>
#include "utest.h"
#define TEST_SECONDS 10
#define TEST_LOOP_TICKS (TEST_SECONDS * RT_TICK_PER_SECOND)
#define TEST_PROGRESS_COUNTS (36)
#define TEST_PROGRESS_ON (TEST_LOOP_TICKS*2/TEST_PROGRESS_COUNTS)
static struct rt_semaphore _thr_exit_sem;
static struct rt_semaphore _ipc_sem;
static rt_atomic_t _progress_counter;
static rt_base_t _timedout_failed_times = 0;
/**
* Test on timedout IPC with racing condition where timedout routine and producer
* thread may race to wakeup sleeper.
*
* This test will fork 2 thread, one producer and one consumer. The producer will
* looping and trigger the IPC on the edge of new tick arrives. The consumer will
* wait on IPC with a timedout of 1 tick.
*/
static void _wait_until_edge(void)
{
rt_tick_t entry_level, current;
rt_base_t random_latency;
entry_level = rt_tick_get();
do
{
current = rt_tick_get();
}
while (current == entry_level);
/* give a random latency for test */
random_latency = rand();
entry_level = current;
for (size_t i = 0; i < random_latency; i++)
{
current = rt_tick_get();
if (current != entry_level)
break;
}
}
static void _producer_entry(void *param)
{
for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
{
_wait_until_edge();
rt_sem_release(&_ipc_sem);
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void _consumer_entry(void *param)
{
int error;
for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
{
error = rt_sem_take_interruptible(&_ipc_sem, 1);
if (error == -RT_ETIMEOUT)
{
_timedout_failed_times++;
}
else
{
if (error != RT_EOK)
uassert_true(0);
}
if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
uassert_true(1);
}
rt_sem_release(&_thr_exit_sem);
return;
}
static void timed_sem_tc(void)
{
rt_thread_t prod = rt_thread_create(
"prod",
_producer_entry,
(void *)0,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
4);
rt_thread_t cons = rt_thread_create(
"cons",
_consumer_entry,
(void *)0,
UTEST_THR_STACK_SIZE,
UTEST_THR_PRIORITY + 1,
100);
rt_thread_startup(prod);
rt_thread_startup(cons);
for (size_t i = 0; i < 2; i++)
{
rt_sem_take(&_thr_exit_sem, RT_WAITING_FOREVER);
}
/* Summary */
LOG_I("Total failed times: %ld(in %d)\n", _timedout_failed_times, TEST_LOOP_TICKS);
}
static rt_err_t utest_tc_init(void)
{
int *pseed = rt_malloc(sizeof(int));
srand(*(int *)pseed);
rt_free(pseed);
rt_sem_init(&_ipc_sem, "ipc", 0, RT_IPC_FLAG_PRIO);
rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_sem_detach(&_ipc_sem);
rt_sem_detach(&_thr_exit_sem);
return RT_EOK;
}
static void testcase(void)
{
UTEST_UNIT_RUN(timed_sem_tc);
}
UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.timed_sem", utest_tc_init, utest_tc_cleanup, TEST_SECONDS * 2);
+12 -4
View File
@@ -22,7 +22,8 @@
#include <rtthread.h>
#include "utest.h"
int recive_sig = 0;
static volatile int recive_sig = 0;
static struct rt_semaphore _received_signal;
void sig_handle_default(int signo)
{
@@ -125,12 +126,15 @@ void rt_signal_wait_thread(void *parm)
(void)sigaddset(&selectset, SIGUSR1);
/* case 5:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: kill, should received. */
if (rt_signal_wait(&selectset, &recive_si, RT_TICK_PER_SECOND) != RT_EOK)
if (rt_signal_wait((void *)&selectset, &recive_si, RT_TICK_PER_SECOND) != RT_EOK)
{
return;
}
recive_sig = recive_si.si_signo;
LOG_I("received signal %d", recive_sig);
rt_sem_release(&_received_signal);
}
static void rt_signal_wait_test(void)
@@ -147,7 +151,7 @@ static void rt_signal_wait_test(void)
rt_thread_mdelay(1);
/* case 5:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: kill, should received. */
uassert_int_equal(rt_thread_kill(t1, SIGUSR1), RT_EOK);
rt_thread_mdelay(1);
rt_sem_take(&_received_signal, RT_WAITING_FOREVER);
uassert_int_equal(recive_sig, SIGUSR1);
return;
@@ -167,7 +171,9 @@ static void rt_signal_wait_test2(void)
/* case 6:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: sleep 2s then kill, should can't received. */
rt_thread_mdelay(2000);
uassert_int_equal(rt_thread_kill(t1, SIGUSR1), RT_EOK);
rt_thread_mdelay(1);
uassert_int_not_equal(
rt_sem_take(&_received_signal, 1),
RT_EOK);
uassert_int_not_equal(recive_sig, SIGUSR1);
return;
@@ -175,11 +181,13 @@ static void rt_signal_wait_test2(void)
static rt_err_t utest_tc_init(void)
{
rt_sem_init(&_received_signal, "utest", 0, RT_IPC_FLAG_PRIO);
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
rt_sem_detach(&_received_signal);
return RT_EOK;
}
+29 -16
View File
@@ -9,6 +9,8 @@
* 2021-10.11 mazhiyuan add idle, yield, suspend, control, priority, delay_until
*/
#define __RT_IPC_SOURCE__ /* include internal API for utest */
#include <rtthread.h>
#include <stdlib.h>
#include "utest.h"
@@ -56,7 +58,7 @@ static void test_dynamic_thread(void)
thread1_entry,
(void *)1,
THREAD_STACK_SIZE,
__current_thread->current_priority + 1,
UTEST_THR_PRIORITY + 1,
THREAD_TIMESLICE - 5);
if (tid1 == RT_NULL)
{
@@ -105,7 +107,7 @@ static void test_static_thread(void)
(void *)2,
&thread2_stack[0],
sizeof(thread2_stack),
__current_thread->current_priority + 1,
UTEST_THR_PRIORITY + 1,
THREAD_TIMESLICE);
if (ret_init != RT_EOK)
{
@@ -139,10 +141,11 @@ __exit:
static void thread3_entry(void *parameter)
{
rt_tick_t tick;
rt_tick_t tick, latency_tick;
tick = rt_tick_get();
rt_thread_delay(15);
if (rt_tick_get() - tick > 16)
latency_tick = rt_tick_get() - tick;
if (latency_tick > 16 || latency_tick < 15)
{
tid3_finish_flag = 1;
tid3_delay_pass_flag = 0;
@@ -160,7 +163,7 @@ static void test_thread_delay(void)
thread3_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority - 1,
UTEST_THR_PRIORITY - 1,
THREAD_TIMESLICE);
if (tid3 == RT_NULL)
{
@@ -210,7 +213,7 @@ static void test_idle_hook(void)
thread4_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority - 1,
UTEST_THR_PRIORITY - 1,
THREAD_TIMESLICE);
if (tid4 == RT_NULL)
{
@@ -264,7 +267,7 @@ static void test_thread_yield(void)
thread5_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority - 1,
UTEST_THR_PRIORITY - 1,
THREAD_TIMESLICE);
if (tid5 == RT_NULL)
{
@@ -283,7 +286,7 @@ static void test_thread_yield(void)
thread6_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority - 1,
UTEST_THR_PRIORITY - 1,
THREAD_TIMESLICE);
if (tid6 == RT_NULL)
{
@@ -319,12 +322,13 @@ static void test_thread_control(void)
{
rt_err_t ret_control = -RT_ERROR;
rt_err_t rst_delete = -RT_ERROR;
rt_sched_lock_level_t slvl;
tid7 = rt_thread_create("thread7",
thread7_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority + 1,
UTEST_THR_PRIORITY + 1,
THREAD_TIMESLICE);
if (tid7 == RT_NULL)
{
@@ -342,12 +346,17 @@ static void test_thread_control(void)
}
rt_thread_mdelay(200);
rt_thread_control(tid7, RT_THREAD_CTRL_CHANGE_PRIORITY, &change_priority);
if (tid7->current_priority != change_priority)
rt_sched_lock(&slvl);
if (rt_sched_thread_get_curr_prio(tid7) != change_priority)
{
LOG_E("rt_thread_control failed!");
uassert_false(1);
rt_sched_unlock(slvl);
goto __exit;
}
rt_sched_unlock(slvl);
rst_delete = rt_thread_control(tid7, RT_THREAD_CTRL_CLOSE, RT_NULL);
if (rst_delete != RT_EOK)
{
@@ -380,7 +389,7 @@ static void test_thread_priority(void)
thread8_entry,
RT_NULL,
THREAD_STACK_SIZE,
__current_thread->current_priority - 1,
UTEST_THR_PRIORITY - 1,
THREAD_TIMESLICE);
if (tid8 == RT_NULL)
{
@@ -448,6 +457,10 @@ static void test_delay_until(void)
rt_kprintf("delta[20] -> %d\n", delta);
uassert_int_equal(delta, 20);
/**
* the rt_kprints above can take few ticks to complete, maybe more than 10
*/
tick = rt_tick_get();
check_tick = tick;
rt_thread_delay(2);
rt_thread_delay_until(&tick, 10);
@@ -495,7 +508,7 @@ void test_timeslice(void)
timeslice_cntB2 = 0;
tidA = rt_thread_create("timeslice", test_timeslice_threadA_entry, RT_NULL,
2048, __current_thread->current_priority + 1, 10);
2048, UTEST_THR_PRIORITY + 1, 10);
if (!tidA)
{
LOG_E("rt_thread_create failed!");
@@ -512,7 +525,7 @@ void test_timeslice(void)
}
tidB1 = rt_thread_create("timeslice", test_timeslice_threadB1_entry, RT_NULL,
2048, __current_thread->current_priority + 2, 2);
2048, UTEST_THR_PRIORITY + 2, 2);
if (!tidB1)
{
LOG_E("rt_thread_create failed!");
@@ -529,7 +542,7 @@ void test_timeslice(void)
}
tidB2 = rt_thread_create("timeslice", test_timeslice_threadB2_entry, RT_NULL,
2048, __current_thread->current_priority + 2, 2);
2048, UTEST_THR_PRIORITY + 2, 2);
if (!tidB2)
{
LOG_E("rt_thread_create failed!");
@@ -655,7 +668,7 @@ void test_thread_yield_nosmp(void)
// thread9_entry,
// RT_NULL,
// THREAD_STACK_SIZE,
// __current_thread->current_priority + 1,
// UTEST_THR_PRIORITY + 1,
// THREAD_TIMESLICE);
// if (tid == RT_NULL)
// {
@@ -695,7 +708,7 @@ void test_thread_yield_nosmp(void)
static rt_err_t utest_tc_init(void)
{
__current_thread = rt_thread_self();
change_priority = __current_thread->current_priority + 5;
change_priority = UTEST_THR_PRIORITY + 5;
tid3_delay_pass_flag = 0;
tid3_finish_flag = 0;
tid4_finish_flag = 0;