rt 0.19.1

A real-time operating system capable of full preemption
Documentation
#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);