rt/cxx/examples/water/water.cpp

71 lines
1.8 KiB
C++

#include "water.hpp"
#include <rt/task.hpp>
#include <rt/trap.hpp>
#include <rt/assert.h>
#include <rt/atomic.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);
}
}
#define STACK_SIZE (RT_STACK_MIN * 2)
RT_TASK(timeout, RT_STACK_MIN, 0);
RT_TASK(hydrogen_loop, STACK_SIZE, 2);
RT_TASK(hydrogen_loop, STACK_SIZE, 2);
RT_TASK(oxygen_loop, STACK_SIZE, 1);