mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
@@ -47,6 +47,10 @@
|
|||||||
#include <rtems/score/userextimpl.h>
|
#include <rtems/score/userextimpl.h>
|
||||||
#include <rtems/score/watchdogimpl.h>
|
#include <rtems/score/watchdogimpl.h>
|
||||||
|
|
||||||
|
#ifdef RTEMS_SMP
|
||||||
|
#include <rtems/score/smpimpl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef T_interrupt_test_state (*T_interrupt_test_handler)(void *);
|
typedef T_interrupt_test_state (*T_interrupt_test_handler)(void *);
|
||||||
|
|
||||||
#define T_INTERRUPT_SAMPLE_COUNT 8
|
#define T_INTERRUPT_SAMPLE_COUNT 8
|
||||||
@@ -61,6 +65,10 @@ typedef struct {
|
|||||||
T_interrupt_test_state (*interrupt)(void *);
|
T_interrupt_test_state (*interrupt)(void *);
|
||||||
void (*blocked)(void *);
|
void (*blocked)(void *);
|
||||||
void *arg;
|
void *arg;
|
||||||
|
#ifdef RTEMS_SMP
|
||||||
|
Per_CPU_Job job;
|
||||||
|
Per_CPU_Job_context job_context;
|
||||||
|
#endif
|
||||||
Watchdog_Control wdg;
|
Watchdog_Control wdg;
|
||||||
User_extensions_Control ext;
|
User_extensions_Control ext;
|
||||||
T_fixture_node node;
|
T_fixture_node node;
|
||||||
@@ -199,11 +207,31 @@ T_interrupt_do_nothing(void *arg)
|
|||||||
(void)arg;
|
(void)arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RTEMS_SMP
|
||||||
|
static void
|
||||||
|
T_interrupt_blocked(void *arg)
|
||||||
|
{
|
||||||
|
T_interrupt_context *ctx;
|
||||||
|
|
||||||
|
ctx = arg;
|
||||||
|
(*ctx->blocked)(ctx->arg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void T_interrupt_thread_switch(Thread_Control *, Thread_Control *);
|
static void T_interrupt_thread_switch(Thread_Control *, Thread_Control *);
|
||||||
|
|
||||||
static T_interrupt_context T_interrupt_instance = {
|
static T_interrupt_context T_interrupt_instance = {
|
||||||
.interrupt = T_interrupt_continue,
|
.interrupt = T_interrupt_continue,
|
||||||
.blocked = T_interrupt_do_nothing,
|
.blocked = T_interrupt_do_nothing,
|
||||||
|
#ifdef RTEMS_SMP
|
||||||
|
.job = {
|
||||||
|
.context = &T_interrupt_instance.job_context
|
||||||
|
},
|
||||||
|
.job_context = {
|
||||||
|
.handler = T_interrupt_blocked,
|
||||||
|
.arg = &T_interrupt_instance
|
||||||
|
},
|
||||||
|
#endif
|
||||||
.wdg = WATCHDOG_INITIALIZER(T_interrupt_watchdog),
|
.wdg = WATCHDOG_INITIALIZER(T_interrupt_watchdog),
|
||||||
.ext = {
|
.ext = {
|
||||||
.Callouts = {
|
.Callouts = {
|
||||||
@@ -263,7 +291,24 @@ T_interrupt_thread_switch(Thread_Control *executing, Thread_Control *heir)
|
|||||||
state = _Atomic_Load_uint(&ctx->state, ATOMIC_ORDER_RELAXED);
|
state = _Atomic_Load_uint(&ctx->state, ATOMIC_ORDER_RELAXED);
|
||||||
|
|
||||||
if (state != T_INTERRUPT_TEST_INITIAL) {
|
if (state != T_INTERRUPT_TEST_INITIAL) {
|
||||||
|
#ifdef RTEMS_SMP
|
||||||
|
Per_CPU_Control *cpu_self;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In SMP configurations, the thread switch extension
|
||||||
|
* runs in a very restricted environment. Interrupts
|
||||||
|
* are disabled and the caller owns the per-CPU lock.
|
||||||
|
* In order to avoid deadlocks at SMP lock level, we
|
||||||
|
* have to use an SMP job which runs later in the
|
||||||
|
* context of the inter-processor interrupt.
|
||||||
|
*/
|
||||||
|
cpu_self = _Per_CPU_Get();
|
||||||
|
_Per_CPU_Add_job(cpu_self, &ctx->job);
|
||||||
|
_SMP_Send_message(_Per_CPU_Get_index(cpu_self),
|
||||||
|
SMP_MESSAGE_PERFORM_JOBS);
|
||||||
|
#else
|
||||||
(*ctx->blocked)(ctx->arg);
|
(*ctx->blocked)(ctx->arg);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,60 @@ T_TEST_CASE(TestInterruptFatal)
|
|||||||
T_unreachable();
|
T_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
suspend(void *arg)
|
||||||
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
rtems_id *id;
|
||||||
|
|
||||||
|
id = arg;
|
||||||
|
sc = rtems_task_suspend(*id);
|
||||||
|
T_step_rsc_success(1, sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static T_interrupt_test_state
|
||||||
|
do_nothing(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
return T_INTERRUPT_TEST_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
resume(void *arg)
|
||||||
|
{
|
||||||
|
T_interrupt_test_state state;
|
||||||
|
|
||||||
|
state = T_interrupt_test_change_state(T_INTERRUPT_TEST_ACTION,
|
||||||
|
T_INTERRUPT_TEST_DONE);
|
||||||
|
|
||||||
|
if (state == T_INTERRUPT_TEST_ACTION) {
|
||||||
|
rtems_status_code sc;
|
||||||
|
rtems_id *id;
|
||||||
|
|
||||||
|
id = arg;
|
||||||
|
sc = rtems_task_resume(*id);
|
||||||
|
T_step_rsc_success(0, sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const T_interrupt_test_config blocked_config = {
|
||||||
|
.action = suspend,
|
||||||
|
.interrupt = do_nothing,
|
||||||
|
.blocked = resume,
|
||||||
|
.max_iteration_count = 10000
|
||||||
|
};
|
||||||
|
|
||||||
|
T_TEST_CASE(TestInterruptBlocked)
|
||||||
|
{
|
||||||
|
T_interrupt_test_state state;
|
||||||
|
rtems_id id;
|
||||||
|
|
||||||
|
T_plan(3);
|
||||||
|
id = rtems_task_self();
|
||||||
|
state = T_interrupt_test(&blocked_config, &id);
|
||||||
|
T_step_eq_int(2, state, T_INTERRUPT_TEST_DONE);
|
||||||
|
}
|
||||||
|
|
||||||
const char rtems_test_name[] = "TTEST 2";
|
const char rtems_test_name[] = "TTEST 2";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user