[utest] add smp testcases
This commit is contained in:
parent
0d87b028ed
commit
f33312abe0
|
@ -77,4 +77,8 @@ config UTEST_SCHEDULER_TC
|
|||
bool "scheduler test"
|
||||
default n
|
||||
|
||||
if RT_USING_SMP
|
||||
rsource "smp/Kconfig"
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -62,4 +62,9 @@ if GetDepend(['UTEST_SCHEDULER_TC']):
|
|||
|
||||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
||||
|
||||
list = os.listdir(cwd)
|
||||
for item in list:
|
||||
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||
group = group + SConscript(os.path.join(item, 'SConscript'))
|
||||
|
||||
Return('group')
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
menu "Kernel SMP Testcase"
|
||||
|
||||
config UTEST_SMP_AFFFINITY_TC
|
||||
bool "smp affinity and thread priority test1"
|
||||
default n
|
||||
|
||||
config UTEST_SMP_ASSIGNED_IDLE_CORE_TC
|
||||
bool "smp threads auto assign to idle cores for test"
|
||||
default n
|
||||
|
||||
config UTEST_SMP_INTERRUPT_PRI_TC
|
||||
bool "smp interrupt priority test"
|
||||
default n
|
||||
|
||||
config UTEST_SMP_SPINLOCK_TC
|
||||
bool "smp spinlock test"
|
||||
default n
|
||||
|
||||
config UTEST_SMP_THREAD_PREEMPTION_TC
|
||||
bool "smp threads preemption test"
|
||||
default n
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,27 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = []
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if GetDepend(['UTEST_SMP_SPINLOCK_TC']):
|
||||
src += ['smp_spinlock_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SMP_ASSIGNED_IDLE_CORE_TC']):
|
||||
src += ['smp_assigned_idle_cores_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SMP_INTERRUPT_PRI_TC']):
|
||||
src += ['smp_interrupt_pri_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SMP_THREAD_PREEMPTION_TC']):
|
||||
src += ['smp_thread_preemption_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SMP_AFFFINITY_TC']):
|
||||
src += ['smp_bind_affinity_tc.c']
|
||||
src += ['smp_affinity_pri1_tc.c']
|
||||
src += ['smp_affinity_pri2_tc.c']
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
/**
|
||||
* @brief Test that threads with low-priority bound cores do not preempt high-priority threads.
|
||||
*
|
||||
* @note Create RT_CPUS_NR threads, thread 0 is bound to core 0, lower priority, the priority of the other threads
|
||||
* for the system's highest and the thread entry function does not let out the CPU control, run the specified
|
||||
* number of times in thread 0 to create a high-priority not bound to the core of the thread, the thread will
|
||||
* be preempted by the core 0 is running on the thread!
|
||||
*/
|
||||
|
||||
/* Number of thread runs */
|
||||
static int run_num = 10;
|
||||
#define THREAD_STACK_SIZE 1024
|
||||
#define THREAD_PRIORITY 2
|
||||
#define LOW_PRIORITY 50
|
||||
#define THIGH_PRIORITY 10
|
||||
static rt_thread_t threads[RT_CPUS_NR];
|
||||
static rt_thread_t temp_thread;
|
||||
static struct rt_spinlock lock;
|
||||
static int thread_inc = 0;
|
||||
static int num = 0;
|
||||
|
||||
static void thread_temp_entry(void *parameter)
|
||||
{
|
||||
int id = 0;
|
||||
while (1)
|
||||
{
|
||||
id = rt_hw_cpu_id();
|
||||
uassert_int_equal(id, 0);
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
rt_thread_delete(temp_thread);
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_entry(void *parameter)
|
||||
{
|
||||
int id = 0;
|
||||
int para = *(int *)parameter;
|
||||
while (1)
|
||||
{
|
||||
thread_inc++;
|
||||
id = rt_hw_cpu_id();
|
||||
if (para == 0)
|
||||
{
|
||||
if (thread_inc == run_num)
|
||||
{
|
||||
uassert_int_equal(id, 0);
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
/* Creating high-priority untied core threads */
|
||||
temp_thread = rt_thread_create("Tn", thread_temp_entry, RT_NULL, THREAD_STACK_SIZE, THIGH_PRIORITY, 20);
|
||||
|
||||
if (temp_thread != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(temp_thread);
|
||||
}
|
||||
}
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_int_not_equal(id, 0);
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void smp_affinity_pri1_tc(void)
|
||||
{
|
||||
static int params[RT_CPUS_NR] = {0};
|
||||
char thread_name[8];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
params[i] = i;
|
||||
}
|
||||
|
||||
/* Creating threads with low priority bindings to core 0 */
|
||||
threads[0] = rt_thread_create("T0", thread_entry, (int *)¶ms[0], THREAD_STACK_SIZE, LOW_PRIORITY, 20);
|
||||
|
||||
if (threads[0] != RT_NULL)
|
||||
{
|
||||
rt_thread_control(threads[0], RT_THREAD_CTRL_BIND_CPU, (void *)0);
|
||||
rt_thread_startup(threads[0]);
|
||||
}
|
||||
|
||||
/* Create high-priority unbound threads with thread functions that don't let out CPU control */
|
||||
for (i = 1; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
rt_snprintf(thread_name, sizeof(thread_name), "T%d", i);
|
||||
threads[i] = rt_thread_create(thread_name, thread_entry, (int *)¶ms[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
|
||||
|
||||
if (threads[i] != RT_NULL)
|
||||
{
|
||||
rt_thread_control(threads[i], RT_THREAD_CTRL_BIND_CPU, (void *)i);
|
||||
rt_thread_startup(threads[i]);
|
||||
}
|
||||
}
|
||||
rt_thread_delay(100);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_spin_lock_init(&lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
for (num = 0; num < RT_CPUS_NR; num++)
|
||||
{
|
||||
rt_thread_delete(threads[num]);
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(smp_affinity_pri1_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.affinity_pri1_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
/**
|
||||
* @brief Threads are automatically balanced across cores.
|
||||
*
|
||||
* @note Create RT_CPUS_NR threads, thread 0 is not bound to core 0, higher priority, the priority of the other
|
||||
* threads for the system's highest and the thread entry function does not let out the CPU control, run the
|
||||
* specified number of times after the creation of thread 0 in thread 0, a low-priority bound to the core 0,
|
||||
* the thread will not preempt the core 0 is running on threads
|
||||
*/
|
||||
|
||||
/* Number of thread runs */
|
||||
static int run_num = 10;
|
||||
#define THREAD_STACK_SIZE 1024
|
||||
#define THREAD_PRIORITY 2
|
||||
#define LOW_PRIORITY 50
|
||||
#define THIGH_PRIORITY 10
|
||||
static rt_thread_t threads[RT_CPUS_NR];
|
||||
static rt_thread_t temp_thread;
|
||||
static struct rt_spinlock lock;
|
||||
static int thread_inc = 0;
|
||||
static int run_flag = 0;
|
||||
static int num = 0;
|
||||
|
||||
static void thread_temp_entry(void *parameter)
|
||||
{
|
||||
run_flag = 1;
|
||||
rt_thread_delete(temp_thread);
|
||||
}
|
||||
|
||||
static void thread_entry(void *parameter)
|
||||
{
|
||||
int id = 0;
|
||||
int para = *(int *)parameter;
|
||||
while (1)
|
||||
{
|
||||
thread_inc++;
|
||||
id = rt_hw_cpu_id();
|
||||
if (para == 0)
|
||||
{
|
||||
if (thread_inc == run_num)
|
||||
{
|
||||
uassert_int_equal(id, 0);
|
||||
temp_thread = rt_thread_create("Tn", thread_temp_entry, RT_NULL, THREAD_STACK_SIZE, LOW_PRIORITY, 20);
|
||||
|
||||
if (temp_thread != RT_NULL)
|
||||
{
|
||||
rt_thread_control(temp_thread, RT_THREAD_CTRL_BIND_CPU, (void *)0);
|
||||
rt_thread_startup(temp_thread);
|
||||
uassert_int_not_equal(run_flag, 1);
|
||||
}
|
||||
}
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_int_not_equal(id, 0);
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void smp_affinity_pri2_tc(void)
|
||||
{
|
||||
static int params[RT_CPUS_NR] = {0};
|
||||
char thread_name[8];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
params[i] = i;
|
||||
}
|
||||
|
||||
threads[0] = rt_thread_create("T0", thread_entry, (int *)¶ms[0], THREAD_STACK_SIZE, THIGH_PRIORITY, 20);
|
||||
|
||||
if (threads[0] != RT_NULL)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_thread_startup(threads[0]);
|
||||
}
|
||||
|
||||
/* Create high-priority unbound threads with thread functions that don't let out CPU control */
|
||||
for (i = 1; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
rt_snprintf(thread_name, sizeof(thread_name), "T%d", i);
|
||||
threads[i] = rt_thread_create(thread_name, thread_entry, (int *)¶ms[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
|
||||
|
||||
if (threads[i] != RT_NULL)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_thread_control(threads[i], RT_THREAD_CTRL_BIND_CPU, (void *)i);
|
||||
rt_thread_startup(threads[i]);
|
||||
}
|
||||
}
|
||||
rt_thread_delay(50);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_spin_lock_init(&lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
for (num = 0; num < RT_CPUS_NR; num++)
|
||||
{
|
||||
rt_thread_delete(threads[num]);
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(smp_affinity_pri2_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.affinity_pri2_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
/**
|
||||
* @brief Threads are automatically balanced across cores.
|
||||
*
|
||||
* @note Create multiple threads untied core threads, run them for a while on each core to see
|
||||
* if the threads are automatically distributed evenly, run for a while to output the threads
|
||||
* running on each core.
|
||||
*/
|
||||
|
||||
#define THREAD_STACK_SIZE 1024
|
||||
#define THREAD_PRIORITY 20
|
||||
static rt_thread_t threads[RT_CPUS_NR];
|
||||
static int tick = 0, finsh_flag = 0;
|
||||
static int num = 0;
|
||||
/* thread entry function */
|
||||
static void thread_entry(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
tick++;
|
||||
if (tick == 100)
|
||||
{
|
||||
/* Output the current core running threads */
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
finsh_flag = 0xA55A;
|
||||
uassert_true(1);
|
||||
}
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_on_idle_core_tc(void)
|
||||
{
|
||||
static int params[RT_CPUS_NR] = {0};
|
||||
char thread_name[8];
|
||||
int i;
|
||||
|
||||
/* Initialise the thread entry parameters */
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
params[i] = i;
|
||||
}
|
||||
|
||||
/* Create RT_CPUS_NR threads and pass the entry parameters for each thread */
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
rt_snprintf(thread_name, sizeof(thread_name), "T%d", i);
|
||||
threads[i] = rt_thread_create(thread_name, thread_entry, ¶ms[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
|
||||
if (threads[i] != RT_NULL)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_thread_startup(threads[i]);
|
||||
}
|
||||
}
|
||||
/* Waiting for test cases to finish */
|
||||
while (finsh_flag != 0xA55A);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_kprintf("[Test case]: created threads are automatically assigned to run on idle cores\r\n");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
for (num = 0; num < RT_CPUS_NR; num++)
|
||||
{
|
||||
rt_thread_delete(threads[num]);
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(thread_on_idle_core_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.assigned_idle_cores_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
/**
|
||||
* @brief Binding core affinity testcase.
|
||||
*
|
||||
* @note Create RT_CPUS_NR threads, thread 0 is bound to core 0, other threads are not bound to specific cores,
|
||||
* after running for a set number of times, count the number of times each core is run on the corresponding core,
|
||||
* thread 0 should always be run on core 0, other threads will be run on different cores.
|
||||
*/
|
||||
|
||||
/* Number of thread runs */
|
||||
static int run_num = 100;
|
||||
#define THREAD_STACK_SIZE 1024
|
||||
#define THREAD_PRIORITY 20
|
||||
static rt_thread_t threads[RT_CPUS_NR];
|
||||
static struct rt_spinlock lock;
|
||||
static int thread_inc[RT_CPUS_NR] = {0};
|
||||
static int thread_tic[RT_CPUS_NR] = {0};
|
||||
static int finsh_flag = 0;
|
||||
static int num = 0;
|
||||
|
||||
static void thread_entry(void *parameter)
|
||||
{
|
||||
int id = 0;
|
||||
int para = *(int *)parameter;
|
||||
while (1)
|
||||
{
|
||||
thread_tic[para]++;
|
||||
id = rt_hw_cpu_id();
|
||||
if (para == id)
|
||||
{
|
||||
thread_inc[para]++;
|
||||
}
|
||||
|
||||
if (thread_tic[para] == run_num)
|
||||
{
|
||||
if (para == 0)
|
||||
uassert_int_equal(thread_inc[para], thread_tic[para]);
|
||||
else
|
||||
uassert_int_not_equal(thread_inc[para], thread_tic[para]);
|
||||
finsh_flag ++;
|
||||
}
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_bind_affinity_tc(void)
|
||||
{
|
||||
static int params[RT_CPUS_NR] = {0};
|
||||
char thread_name[8];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
params[i] = i;
|
||||
}
|
||||
|
||||
/* Create RT_CPUS_NR threads Thread 0 is bound to core 0 Other threads are not bound */
|
||||
for (i = 0; i < RT_CPUS_NR; i++)
|
||||
{
|
||||
rt_snprintf(thread_name, sizeof(thread_name), "thread%d", i);
|
||||
threads[i] = rt_thread_create(thread_name, thread_entry, (int *)¶ms[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
|
||||
if (i == 0)
|
||||
{
|
||||
rt_thread_control(threads[0], RT_THREAD_CTRL_BIND_CPU, (void *)0);
|
||||
}
|
||||
if (threads[i] != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(threads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
while (finsh_flag != RT_CPUS_NR);
|
||||
|
||||
/* Displays the number of times a thread was executed on the relevant core */
|
||||
for (j = 0; j < RT_CPUS_NR; j++)
|
||||
{
|
||||
rt_spin_lock(&lock);
|
||||
rt_kprintf("Total runs[%d], Number of times thread[%d] run on [core%d]: [%4d], always run at core%d ? %s \r\n", run_num, j, j, thread_inc[j], j, (thread_inc[j] == run_num) ? "yes" : "no");
|
||||
rt_spin_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_spin_lock_init(&lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
for (num = 0; num < RT_CPUS_NR; num++)
|
||||
{
|
||||
rt_thread_delete(threads[num]);
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(thread_bind_affinity_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.bind_affinity_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <interrupt.h>
|
||||
|
||||
/**
|
||||
* @brief Setting the Interrupt Priority Test.
|
||||
*
|
||||
* @note Without turning off interrupts, interrupts respond in the order in which they are triggered.
|
||||
* With interrupts turned off, low and high priority interrupts are triggered sequentially,
|
||||
* and when interrupts are turned on, high priority interrupts respond first.
|
||||
*/
|
||||
|
||||
#define RES_VAL 0X0
|
||||
#define SET_VAL 0XA
|
||||
#define RT_SPI_1 1
|
||||
#define RT_SPI_2 2
|
||||
#define RT_SPI_PRI_HIGH 120
|
||||
#define RT_SPI_PRI_LOW 140
|
||||
|
||||
static int mode = 0;
|
||||
static int ipi_val[2] = {0, 0};
|
||||
|
||||
/* Software Interrupt 1 Service Functions */
|
||||
static void rt_scheduler_ipi1_handler(int vector, void *param)
|
||||
{
|
||||
ipi_val[0] = SET_VAL;
|
||||
if (mode == 0)
|
||||
{
|
||||
uassert_true(ipi_val[0] > ipi_val[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ipi_val[0] = RES_VAL;
|
||||
ipi_val[1] = RES_VAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Software Interrupt 2 Service Functions */
|
||||
static void rt_scheduler_ipi2_handler(int vector, void *param)
|
||||
{
|
||||
ipi_val[1] = SET_VAL;
|
||||
if (mode == 0)
|
||||
{
|
||||
ipi_val[0] = RES_VAL;
|
||||
ipi_val[1] = RES_VAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_true(ipi_val[0] < ipi_val[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Interrupt priority testcases 1 */
|
||||
static void int_pri1_tc(void)
|
||||
{
|
||||
mode = 0;
|
||||
unsigned int pri1, pri2;
|
||||
pri1 = rt_hw_interrupt_get_priority(RT_SPI_1);
|
||||
pri2 = rt_hw_interrupt_get_priority(RT_SPI_2);
|
||||
|
||||
if (pri1 < pri2)
|
||||
uassert_true(pri1 < pri2);
|
||||
|
||||
/* Trigger interrupt */
|
||||
rt_hw_ipi_send(RT_SPI_1, 0x1);
|
||||
rt_hw_ipi_send(RT_SPI_2, 0x1);
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
|
||||
/* Interrupt priority testcases 2 */
|
||||
static void int_pri2_tc(void)
|
||||
{
|
||||
mode = 1;
|
||||
unsigned int pri1, pri2;
|
||||
pri1 = rt_hw_interrupt_get_priority(RT_SPI_1);
|
||||
pri2 = rt_hw_interrupt_get_priority(RT_SPI_2);
|
||||
|
||||
if (pri1 < pri2)
|
||||
uassert_true(pri1 < pri2);
|
||||
|
||||
rt_base_t level = rt_hw_local_irq_disable();
|
||||
/* Trigger interrupt */
|
||||
rt_hw_ipi_send(RT_SPI_1, 0x1);
|
||||
rt_hw_ipi_send(RT_SPI_2, 0x1);
|
||||
rt_hw_local_irq_enable(level);
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
/* Setting the priority of software interrupts */
|
||||
rt_hw_interrupt_set_priority(RT_SPI_1, RT_SPI_PRI_LOW);
|
||||
rt_hw_interrupt_set_priority(RT_SPI_2, RT_SPI_PRI_HIGH);
|
||||
/* Register software interrupt service functions */
|
||||
rt_hw_ipi_handler_install(RT_SPI_1, rt_scheduler_ipi1_handler);
|
||||
rt_hw_ipi_handler_install(RT_SPI_2, rt_scheduler_ipi2_handler);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(int_pri1_tc);
|
||||
UTEST_UNIT_RUN(int_pri2_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.interrupt_pri_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-13 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <interrupt.h>
|
||||
|
||||
/**
|
||||
* @brief Spinlock testcase.
|
||||
*
|
||||
* @note Create multiple threads and use spinlocks to protect shared memory
|
||||
*/
|
||||
|
||||
#define THREAD_PRIORITY 20
|
||||
#define THREAD_TIMESLICE 20
|
||||
#define THREAD_STACK_SIZE 1024
|
||||
static rt_thread_t thread1;
|
||||
static rt_thread_t thread2;
|
||||
static rt_uint8_t finsh_flag = 0;
|
||||
static struct rt_spinlock lock;
|
||||
static rt_uint8_t number1, number2 = 0;
|
||||
|
||||
static void rt_thread_entry1(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
rt_spin_lock(&lock);
|
||||
number1++;
|
||||
rt_thread_yield();
|
||||
number2++;
|
||||
rt_spin_unlock(&lock);
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
static void rt_thread_entry2(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
rt_spin_lock(&lock);
|
||||
uassert_int_equal(number1, number2);
|
||||
number1++;
|
||||
number2++;
|
||||
rt_spin_unlock(&lock);
|
||||
if (number1 >= 10)
|
||||
{
|
||||
finsh_flag = 1;
|
||||
}
|
||||
rt_thread_delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
static void smp_spinlock_tc(void)
|
||||
{
|
||||
thread1 = rt_thread_create("T1", rt_thread_entry1, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
|
||||
if (thread1 != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(thread1);
|
||||
}
|
||||
|
||||
thread2 = rt_thread_create("T2", rt_thread_entry2, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY - 1, 20);
|
||||
if (thread2 != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(thread2);
|
||||
}
|
||||
while (finsh_flag == 0);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_spin_lock_init(&lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
rt_thread_delete(thread1);
|
||||
rt_thread_delete(thread2);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(smp_spinlock_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.spinlock_tc", utest_tc_init, utest_tc_cleanup, 10);
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-08-10 RV the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
/**
|
||||
* @brief Thread Preemption Test with Different Priorities.
|
||||
*
|
||||
* @note Create multiple threads, low-priority threads run first,
|
||||
* high-priority threads preempt low-priority threads, and
|
||||
* print the current status of each core in the thread's entry function.
|
||||
*/
|
||||
|
||||
#define THREAD_PRIORITY_HIGH 21
|
||||
#define THREAD_PRIORITY_LOW 30
|
||||
|
||||
static rt_thread_t threads[2];
|
||||
static struct rt_spinlock lock;
|
||||
|
||||
/* High Priority Thread */
|
||||
static void thread_high_entry(void *parameter)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_spin_lock(&lock);
|
||||
rt_kprintf("High priority thread is running\n");
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
rt_spin_unlock(&lock);
|
||||
}
|
||||
|
||||
/* Low Priority Thread */
|
||||
static void thread_low_entry(void *parameter)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_spin_lock(&lock);
|
||||
rt_kprintf("Low priority thread is running\n");
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
rt_spin_unlock(&lock);
|
||||
}
|
||||
|
||||
static void thread_preemptions_tc(void)
|
||||
{
|
||||
/* Creating low-priority thread */
|
||||
threads[0] = rt_thread_create("tlow", thread_low_entry, RT_NULL, 1024, THREAD_PRIORITY_LOW, 10);
|
||||
if (threads[0] != RT_NULL)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_thread_startup(threads[0] );
|
||||
}
|
||||
|
||||
rt_thread_delay(5);
|
||||
/* Creating high-priority thread */
|
||||
threads[1] = rt_thread_create("thigh", thread_high_entry, RT_NULL, 1024, THREAD_PRIORITY_HIGH, 10);
|
||||
if (threads[1] != RT_NULL)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_thread_startup(threads[1]);
|
||||
}
|
||||
rt_thread_delay(50);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_spin_lock_init(&lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(thread_preemptions_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.smp.thread_preemptions_tc", utest_tc_init, utest_tc_cleanup, 10);
|
Loading…
Reference in New Issue