use alloc::collections::VecDeque; use spin::{Once, Mutex, MutexGuard}; use crate::event; use crate::scheme::SchemeId; use crate::syscall::data::TimeSpec; use crate::syscall::flag::{CLOCK_MONOTONIC, CLOCK_REALTIME, EVENT_READ}; use crate::time; #[derive(Debug)] struct Timeout { pub scheme_id: SchemeId, pub event_id: usize, pub clock: usize, pub time: u128, } type Registry = VecDeque; static REGISTRY: Once> = Once::new(); /// Initialize registry, called if needed fn init_registry() -> Mutex { Mutex::new(Registry::new()) } /// Get the global timeouts list fn registry() -> MutexGuard<'static, Registry> { REGISTRY.call_once(init_registry).lock() } pub fn register(scheme_id: SchemeId, event_id: usize, clock: usize, time: TimeSpec) { let mut registry = registry(); registry.push_back(Timeout { scheme_id, event_id, clock, time: (time.tv_sec as u128 * time::NANOS_PER_SEC) + (time.tv_nsec as u128) }); } pub fn trigger() { let mut registry = registry(); let mono = time::monotonic(); let real = time::realtime(); let mut i = 0; while i < registry.len() { let trigger = match registry[i].clock { CLOCK_MONOTONIC => { let time = registry[i].time; mono >= time }, CLOCK_REALTIME => { let time = registry[i].time; real >= time }, clock => { println!("timeout::trigger: unknown clock {}", clock); true } }; if trigger { let timeout = registry.remove(i).unwrap(); event::trigger(timeout.scheme_id, timeout.event_id, EVENT_READ); } else { i += 1; } } }