rt/examples/water/water.c

69 lines
1.8 KiB
C

#include "water.h"
#include <rt/assert.h>
#include <rt/atomic.h>
#include <rt/log.h>
#include <rt/task.h>
#include <rt/trap.h>
static rt_atomic_uint32_t hydrogen_bonded = 0;
static rt_atomic_uint32_t oxygen_bonded = 0;
static rt_atomic_uint32_t water_formed = 0;
void make_water(void)
{
rt_atomic_fetch_add(&water_formed, 1, RT_ATOMIC_RELAXED);
}
#define TICKS_TO_RUN 1000
static void timeout(void)
{
rt_task_drop_privilege();
rt_task_sleep(TICKS_TO_RUN);
const uint32_t w = rt_atomic_load(&water_formed, RT_ATOMIC_RELAXED);
const uint32_t h = rt_atomic_load(&hydrogen_bonded, RT_ATOMIC_RELAXED);
const uint32_t o = rt_atomic_load(&oxygen_bonded, RT_ATOMIC_RELAXED);
/* The oxygen or hydrogen may not have bonded by the time rt_trap is called
* after making a water molecule, so allow for o and h to be one molecule's
* worth below expected value or exactly equal to it. */
const uint32_t o_lo = w - 1;
const uint32_t o_hi = w;
const uint32_t h_lo = (w - 1) * 2;
const uint32_t h_hi = w * 2;
rt_assert(o >= o_lo, "not enough oxygen was bonded");
rt_assert(o <= o_hi, "too much oxygen was bonded");
rt_assert(h >= h_lo, "not enough hydrogen was bonded");
rt_assert(h <= h_hi, "too much hydrogen was bonded");
rt_trap();
}
static void oxygen_loop(void)
{
rt_task_drop_privilege();
for (;;)
{
oxygen();
rt_atomic_fetch_add(&oxygen_bonded, 1, RT_ATOMIC_RELAXED);
}
}
static void hydrogen_loop(void)
{
rt_task_drop_privilege();
for (;;)
{
hydrogen();
rt_atomic_fetch_add(&hydrogen_bonded, 1, RT_ATOMIC_RELAXED);
}
}
RT_TASK(timeout, RT_STACK_MIN, 3);
RT_TASK(hydrogen_loop, RT_STACK_MIN, 1);
RT_TASK(hydrogen_loop, RT_STACK_MIN, 1);
RT_TASK(oxygen_loop, RT_STACK_MIN, 2);