Files
RedBear-OS/src/context/timeout.rs
T
2022-11-14 10:10:17 -07:00

73 lines
1.8 KiB
Rust

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<Timeout>;
static REGISTRY: Once<Mutex<Registry>> = Once::new();
/// Initialize registry, called if needed
fn init_registry() -> Mutex<Registry> {
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;
}
}
}