rt 0.17.0

A real-time operating system capable of full preemption
Documentation
#include <rt/cond.h>

#include <rt/atomic.h>
#include <rt/mutex.h>
#include <rt/syscall.h>
#include <rt/task.h>
#include <rt/tick.h>
#include <rt/trace.h>

#include <limits.h>

void rt_cond_signal(struct rt_cond *cond)
{
    rt_sem_post(&cond->sem);
}

void rt_cond_broadcast(struct rt_cond *cond)
{
    rt_sem_post_n(&cond->sem, INT_MAX);
}

void rt_cond_wait(struct rt_cond *cond, struct rt_mutex *mutex)
{
    /* Decrement the semaphore while still holding the mutex so that
     * signals from higher priority tasks on the same monitor can see
     * there is a waiter. */
    const int value =
        rt_atomic_fetch_sub(&cond->sem.value, 1, RT_ATOMIC_ACQUIRE);
    rt_trace_sem_update(&cond->sem, value, value - 1);
    if (value > 0)
    {
        /* The condition was signaled after the caller evaluated the predicate,
         * so let the caller re-evaluate it without releasing the mutex. */
        return;
    }
    rt_mutex_unlock(mutex);
    rt_syscall_sem_wait(&cond->sem);
    rt_mutex_lock(mutex);
}

bool rt_cond_timedwait(struct rt_cond *cond, struct rt_mutex *mutex,
                       unsigned long ticks)
{
    unsigned long start_tick = rt_tick_count();
    const int value =
        rt_atomic_fetch_sub(&cond->sem.value, 1, RT_ATOMIC_ACQUIRE);
    rt_trace_sem_update(&cond->sem, value, value - 1);
    if (value > 0)
    {
        return true;
    }
    rt_mutex_unlock(mutex);
    if ((ticks == 0) || !rt_syscall_sem_timedwait(&cond->sem, ticks))
    {
        return false;
    }
    rt_tick_elapse(&ticks, &start_tick);
    return rt_mutex_timedlock(mutex, ticks);
}