#include <rt/arch/irq.h>
#include <rt/arch/signal.h>
#include <rt/exit.h>
#include <rt/panic.h>
#include <rt/pend_function.h>
#include <rt/sem.h>
#include <rt/task.h>
#include <rt/trace.h>
static RT_SEM(sigsegv_sem, 0);
static RT_SEM(irq_sem, 0);
static void sigsegv_handler(int signum)
{
rt_trace_interrupt_start(signum);
struct rt_task *const task = rt_task_self();
rt_assert(rt_task_pend_terminate(task), "sigsegv failed to pend terminate");
rt_sem_post(&sigsegv_sem);
rt_trace_interrupt_end(signum);
}
static struct rt_task rt_atomic(*) sleeper_ptr, rt_atomic(*) waiter_ptr,
rt_atomic(*) yielder_ptr;
void rt_irq_handler(void)
{
struct rt_task *const sleeper_task =
rt_atomic_load(&sleeper_ptr, RT_ATOMIC_ACQUIRE);
rt_assert(sleeper_task != NULL, "sleeper task pointer is NULL");
rt_assert(rt_task_pend_terminate(sleeper_task),
"failed to pend terminate for sleeper");
struct rt_task *const waiter_task =
rt_atomic_load(&waiter_ptr, RT_ATOMIC_ACQUIRE);
rt_assert(waiter_task != NULL, "waiter task pointer is NULL");
rt_assert(rt_task_pend_terminate(waiter_task),
"failed to pend terminate for waiter");
struct rt_task *const yielder_task =
rt_atomic_load(&yielder_ptr, RT_ATOMIC_ACQUIRE);
rt_assert(yielder_task != NULL, "yielder task pointer is NULL");
rt_assert(rt_task_pend_terminate(yielder_task),
"failed to pend terminate for yielder");
rt_sem_post(&irq_sem);
}
static void segver(void)
{
(void)raise(SIGSEGV);
rt_panic("segver still running after raising SIGSEGV");
}
static void sleeper(void)
{
rt_atomic_store(&sleeper_ptr, rt_task_self(), RT_ATOMIC_RELEASE);
rt_task_sleep(5);
rt_panic("sleeper was not terminated");
}
static void waiter(void)
{
rt_atomic_store(&waiter_ptr, rt_task_self(), RT_ATOMIC_RELEASE);
static RT_SEM(sem, 0);
rt_sem_wait(&sem);
rt_panic("waiter was not terminated");
}
static void yielder(void)
{
rt_atomic_store(&yielder_ptr, rt_task_self(), RT_ATOMIC_RELEASE);
rt_task_yield();
rt_panic("yielder was not terminated");
}
static void task0(void)
{
struct sigaction action;
action.sa_flags = SA_RESTART;
action.sa_handler = sigsegv_handler;
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGPENDSYSCALL);
sigaction(SIGSEGV, &action, NULL);
rt_assert(rt_sem_timedwait(&sigsegv_sem, 10),
"sigsegv handler was not invoked");
rt_assert(rt_sem_timedwait(&irq_sem, 10), "irq handler was not invoked");
rt_exit();
}
static void irqer(void)
{
rt_irq_pend();
}
RT_TASK(task0, RT_STACK_MIN, 0);
RT_TASK(sleeper, RT_STACK_MIN, 0);
RT_TASK(waiter, RT_STACK_MIN, 0);
RT_TASK(yielder, RT_STACK_MIN, 1);
RT_TASK(irqer, RT_STACK_MIN, 1);
RT_TASK(segver, RT_STACK_MIN, 1);