Files
RedBear-OS/src/context/timeout.rs
T
2026-05-13 10:46:38 +07:00

87 lines
2.1 KiB
Rust

use alloc::collections::VecDeque;
use crate::{
event,
scheme::SchemeId,
sync::{CleanLockToken, LockToken, Mutex, MutexGuard, L0, L1},
syscall::{
data::TimeSpec,
flag::{CLOCK_MONOTONIC, CLOCK_REALTIME, EVENT_READ},
},
time,
};
#[derive(Debug)]
struct Timeout {
pub scheme_id: SchemeId,
pub event_id: usize,
pub clock: usize,
pub time: u128,
}
type Registry = VecDeque<Timeout>;
static REGISTRY: Mutex<L1, Registry> = Mutex::new(Registry::new());
/// Get the global timeouts list
fn registry(token: LockToken<'_, L0>) -> MutexGuard<'_, L1, Registry> {
REGISTRY.lock(token)
}
pub fn get_timeout_stat(token: &mut CleanLockToken) -> usize {
REGISTRY.lock(token.token()).len()
}
pub fn register(
scheme_id: SchemeId,
event_id: usize,
clock: usize,
time: TimeSpec,
token: &mut CleanLockToken,
) {
let mut registry = registry(token.token());
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(token: &mut CleanLockToken) {
let mono = time::monotonic(token);
let real = time::realtime(token);
let mut i = 0;
loop {
let mut registry = registry(token.token());
let timeout = if 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 {
registry.swap_remove_back(i).unwrap()
} else {
i += 1;
continue;
}
} else {
break;
};
drop(registry);
event::trigger(timeout.scheme_id, timeout.event_id, EVENT_READ, token);
}
}