tests: adding test cases for arch-dependent SMP function

Add one another test case for testing both arch_curr_cpu() and
arch_sched_ipi() architecture layer interface.

Signed-off-by: Enjia Mai <enjiax.mai@intel.com>
This commit is contained in:
Enjia Mai 2020-05-28 11:29:50 +08:00 committed by Anas Nashif
parent 0cb8c50238
commit 7ac40aabc0
4 changed files with 133 additions and 3 deletions

View file

@ -747,6 +747,15 @@ config SCHED_IPI_SUPPORTED
take an interrupt, which can be arbitrarily far in the
future).
config TRACE_SCHED_IPI
bool "Enable Test IPI"
help
When true, it will add a hook into z_sched_ipi(), in order
to check if schedule IPI has called or not, for testing
purpose.
depends on SCHED_IPI_SUPPORTED
depends on MP_NUM_CPUS>1
endmenu
config TICKLESS_IDLE

View file

@ -1268,12 +1268,19 @@ void z_impl_k_wakeup(k_tid_t thread)
}
}
#ifdef CONFIG_TRACE_SCHED_IPI
extern void z_trace_sched_ipi(void);
#endif
#ifdef CONFIG_SMP
void z_sched_ipi(void)
{
/* NOTE: When adding code to this, make sure this is called
* at appropriate location when !CONFIG_SCHED_IPI_SUPPORTED.
*/
#ifdef CONFIG_TRACE_SCHED_IPI
z_trace_sched_ipi();
#endif
}
void z_sched_abort(struct k_thread *thread)

View file

@ -1,2 +1,3 @@
CONFIG_ZTEST=y
CONFIG_SMP=y
CONFIG_TRACE_SCHED_IPI=y

View file

@ -189,8 +189,8 @@ static void spin_for_threads_exit(void)
k_busy_wait(DELAY_US);
}
static void spawn_threads(int prio, int thread_num,
int equal_prio, k_thread_entry_t thread_entry, int delay)
static void spawn_threads(int prio, int thread_num, int equal_prio,
k_thread_entry_t thread_entry, int delay)
{
int i;
@ -441,6 +441,117 @@ void test_wakeup_threads(void)
cleanup_resources();
}
/* a thread for testing get current cpu */
static void thread_get_cpu_entry(void *p1, void *p2, void *p3)
{
int bsp_id = *(int *)p1;
int cpu_id = -1;
/* get current cpu number for running thread */
_cpu_t *curr_cpu = arch_curr_cpu();
/**TESTPOINT: call arch_curr_cpu() to get cpu struct */
zassert_true(curr_cpu != NULL,
"test failed to get current cpu.");
cpu_id = curr_cpu->id;
zassert_true(bsp_id != cpu_id,
"should not be the same with our BSP");
/* loop forever to ensure running on this CPU */
while (1) {
k_busy_wait(DELAY_US);
};
}
/**
* @brief Test get a pointer of CPU
*
* @ingroup kernel_smp_tests
*
* @details Architecture layer provides a mechanism to return a pointer to the
* current kernel CPU record of the running CPU.
*
* We call arch_curr_cpu() and get it's member, both in main and spwaned thread
* speratively, and compare them. They shall be different in SMP enviornment.
*
* @see arch_curr_cpu()
*/
void test_get_cpu(void)
{
k_tid_t thread_id;
/* get current cpu number */
int cpu_id = arch_curr_cpu()->id;
thread_id = k_thread_create(&t2, t2_stack, T2_STACK_SIZE,
(k_thread_entry_t)thread_get_cpu_entry,
&cpu_id, NULL, NULL,
K_PRIO_COOP(2),
K_INHERIT_PERMS, K_NO_WAIT);
k_busy_wait(DELAY_US);
k_thread_abort(thread_id);
}
#ifdef CONFIG_TRACE_SCHED_IPI
/* global variable for testing send IPI */
static int sched_ipi_has_called = -1;
void z_trace_sched_ipi(void)
{
sched_ipi_has_called++;
}
/**
* @brief Test interprocessor interrupt
*
* @ingroup kernel_smp_tests
*
* @details Architecture layer provides a mechanism to issue an interprocessor
* interrupt to all other CPUs in the system that calls the scheduler IPI
* handler.
*
* We simply add a hook in z_sched_ipi(), in order to check if it has been
* called once in another CPU except the caller, when arch_sched_ipi() is
* called.
*
* @see arch_sched_ipi()
*/
void test_smp_ipi(void)
{
TC_PRINT("cpu num=%d", CONFIG_MP_NUM_CPUS);
sched_ipi_has_called = 0;
k_busy_wait(DELAY_US);
/* It shouldn't enter our IPI interrupt handler at this moment */
zassert_true(sched_ipi_has_called == 0, "shouldn't receive IPI,(%d)",
sched_ipi_has_called);
for (int i = 1; i <= 3 ; i++) {
/* issue a sched ipi to tell other CPU to run thread */
arch_sched_ipi();
/* do busy wait here until get IPI */
k_busy_wait(DELAY_US);
/**TESTPOINT: check if enter our IPI interrupt handler */
zassert_true(sched_ipi_has_called == i,
"did not receive IPI.(%d)",
sched_ipi_has_called);
}
}
#else
void test_smp_ipi(void)
{
ztest_test_skip();
}
#endif
void test_main(void)
{
/* Sleep a bit to guarantee that both CPUs enter an idle
@ -456,7 +567,9 @@ void test_main(void)
ztest_unit_test(test_preempt_resched_threads),
ztest_unit_test(test_yield_threads),
ztest_unit_test(test_sleep_threads),
ztest_unit_test(test_wakeup_threads)
ztest_unit_test(test_wakeup_threads),
ztest_unit_test(test_smp_ipi),
ztest_unit_test(test_get_cpu)
);
ztest_run_test_suite(smp);
}