static HYDROGEN_BONDED: AtomicU32 = AtomicU32::new(0); static OXYGEN_BONDED: AtomicU32 = AtomicU32::new(0); static WATER_FORMED: AtomicU32 = AtomicU32::new(0); fn make_water() { WATER_FORMED.fetch_add(1, Ordering::Relaxed); } fn timeout() { rt::task::drop_privilege(); rt::task::sleep(1000); let w = WATER_FORMED.load(Ordering::Relaxed); let h = HYDROGEN_BONDED.load(Ordering::Relaxed); let o = OXYGEN_BONDED.load(Ordering::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. */ let o_lo = w - 1; let o_hi = w; let h_lo = (w - 1) * 2; let h_hi = w * 2; assert!(o >= o_lo, "not enough oxygen was bonded"); assert!(o <= o_hi, "too much oxygen was bonded"); assert!(h >= h_lo, "not enough hydrogen was bonded"); assert!(h <= h_hi, "too much hydrogen was bonded"); rt::trap(); } fn oxygen_loop() { rt::task::drop_privilege(); loop { oxygen(); OXYGEN_BONDED.fetch_add(1, Ordering::Relaxed); } } fn hydrogen_loop() { rt::task::drop_privilege(); loop { hydrogen(); HYDROGEN_BONDED.fetch_add(1, Ordering::Relaxed); } } const STACK_SIZE: usize = rt::stack::MIN * 8; rt::task!(timeout, STACK_SIZE, 0); rt::task!(hydrogen_loop, STACK_SIZE, 2); rt::task!(hydrogen_loop, STACK_SIZE, 2); rt::task!(oxygen_loop, STACK_SIZE, 1);