use crate::stack::Stack;
use std::sync::atomic::Ordering;
use std::sync::{Once, OnceLock};
use std::time::{Duration, Instant};
use super::{ACTIVE_STRANDS, SHUTDOWN_CONDVAR, SHUTDOWN_MUTEX};
static SCHEDULER_INIT: Once = Once::new();
static SCHEDULER_START_TIME: OnceLock<Instant> = OnceLock::new();
pub(super) const DEFAULT_STACK_SIZE: usize = 0x20000;
const DEFAULT_POOL_CAPACITY: usize = 10000;
pub(super) fn parse_stack_size(env_value: Option<String>) -> usize {
match env_value {
Some(val) => match val.parse::<usize>() {
Ok(0) => {
eprintln!(
"Warning: SEQ_STACK_SIZE=0 is invalid, using default {}",
DEFAULT_STACK_SIZE
);
DEFAULT_STACK_SIZE
}
Ok(size) => size,
Err(_) => {
eprintln!(
"Warning: SEQ_STACK_SIZE='{}' is not a valid number, using default {}",
val, DEFAULT_STACK_SIZE
);
DEFAULT_STACK_SIZE
}
},
None => DEFAULT_STACK_SIZE,
}
}
pub fn scheduler_elapsed() -> Option<Duration> {
SCHEDULER_START_TIME.get().map(|start| start.elapsed())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_scheduler_init() {
SCHEDULER_INIT.call_once(|| {
let stack_size = parse_stack_size(std::env::var("SEQ_STACK_SIZE").ok());
let pool_capacity = std::env::var("SEQ_POOL_CAPACITY")
.ok()
.and_then(|s| s.parse().ok())
.filter(|&v| v > 0)
.unwrap_or(DEFAULT_POOL_CAPACITY);
may::config()
.set_stack_size(stack_size)
.set_pool_capacity(pool_capacity);
SCHEDULER_START_TIME.get_or_init(Instant::now);
#[cfg(unix)]
{
use std::sync::atomic::AtomicBool;
static SIGINT_RECEIVED: AtomicBool = AtomicBool::new(false);
extern "C" fn sigint_handler(_: libc::c_int) {
if SIGINT_RECEIVED.swap(true, Ordering::SeqCst) {
unsafe { libc::_exit(130) }; }
std::process::exit(130);
}
unsafe {
libc::signal(
libc::SIGINT,
sigint_handler as *const () as libc::sighandler_t,
);
}
}
#[cfg(feature = "diagnostics")]
crate::diagnostics::install_signal_handler();
#[cfg(feature = "diagnostics")]
crate::watchdog::install_watchdog();
});
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_scheduler_run() -> Stack {
let mut guard = SHUTDOWN_MUTEX.lock().expect(
"scheduler_run: shutdown mutex poisoned - strand panicked during shutdown synchronization",
);
while ACTIVE_STRANDS.load(Ordering::Acquire) > 0 {
guard = SHUTDOWN_CONDVAR
.wait(guard)
.expect("scheduler_run: condvar wait failed - strand panicked during shutdown wait");
}
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_scheduler_shutdown() {
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_wait_all_strands() {
let mut guard = SHUTDOWN_MUTEX.lock()
.expect("wait_all_strands: shutdown mutex poisoned - strand panicked during shutdown synchronization");
while ACTIVE_STRANDS.load(Ordering::Acquire) > 0 {
guard = SHUTDOWN_CONDVAR
.wait(guard)
.expect("wait_all_strands: condvar wait failed - strand panicked during shutdown wait");
}
}