use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::{Duration, Instant};
static ITERS_SLEEP: AtomicU64 = AtomicU64::new(0);
static ITERS_CHURN: AtomicU64 = AtomicU64::new(0);
static STOP: AtomicBool = AtomicBool::new(false);
static WORKERS_DONE: AtomicU64 = AtomicU64::new(0);
fn sleeper_rt(seed: u64, max_iters: u64) {
let mut x = seed | 1;
let mut iters = 0u64;
while !STOP.load(Ordering::Relaxed) && iters < max_iters {
iters += 1;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
let sleep_us = 200 + (x % 600); let wait_us = 100 + (x % 1200);
go_lib::__main_entry(move || {
for _ in 0..8 {
go_lib::go!(move || {
go_lib::sleep(Duration::from_micros(sleep_us));
});
}
let t0 = Instant::now();
while t0.elapsed() < Duration::from_micros(wait_us) {
std::hint::spin_loop();
}
});
ITERS_SLEEP.fetch_add(1, Ordering::Relaxed);
}
WORKERS_DONE.fetch_add(1, Ordering::Relaxed);
}
fn churn_rt(max_iters: u64) {
let mut iters = 0u64;
while !STOP.load(Ordering::Relaxed) && iters < max_iters {
iters += 1;
go_lib::__main_entry(|| {
const PAIRS: usize = 8;
let (done_tx, done_rx) = go_lib::chan::chan::<()>(PAIRS);
for _ in 0..PAIRS {
let (tx, rx) = go_lib::chan::chan::<i32>(0);
let dtx = done_tx.clone();
go_lib::go!(move || {
for _ in 0..4 {
let v = rx.recv();
assert!(v.is_some());
}
dtx.send(());
});
go_lib::go!(move || {
for i in 0..4 {
tx.send(i);
}
});
}
for _ in 0..PAIRS {
done_rx.recv();
}
});
ITERS_CHURN.fetch_add(1, Ordering::Relaxed);
}
WORKERS_DONE.fetch_add(1, Ordering::Relaxed);
}
fn main() {
let secs: u64 = std::env::args()
.nth(1)
.and_then(|s| s.parse().ok())
.unwrap_or(30);
let max_iters: u64 = std::env::args()
.nth(2)
.and_then(|s| s.parse().ok())
.unwrap_or(300);
const N_WORKERS: u64 = 8;
let mut handles = Vec::new();
for i in 0..4u64 {
handles.push(std::thread::spawn(move || {
sleeper_rt(0x9e3779b9 ^ (i + 1), max_iters)
}));
}
for _ in 0..4 {
handles.push(std::thread::spawn(move || churn_rt(max_iters)));
}
let t0 = Instant::now();
while t0.elapsed() < Duration::from_secs(secs)
&& WORKERS_DONE.load(Ordering::Relaxed) < N_WORKERS
{
std::thread::sleep(Duration::from_secs(1));
eprintln!(
"[{:>3}s] sleeper iters: {}, churn iters: {}, workers done: {}",
t0.elapsed().as_secs(),
ITERS_SLEEP.load(Ordering::Relaxed),
ITERS_CHURN.load(Ordering::Relaxed),
WORKERS_DONE.load(Ordering::Relaxed),
);
}
STOP.store(true, Ordering::Relaxed);
for h in handles {
h.join().unwrap();
}
eprintln!("stress completed without crash");
}