//! Events the kernel reports by signalling a notification: a process's //! death, a deadline passing. One timer per process. use types::{badge::Badge, generation::Generation, id::NotificationId, id::ProcessId, time::Ticks}; use crate::process::MAX_PROCESSES; #[cfg(test)] #[path = "timer_tests.rs"] mod tests; /// A notification as a capability named it; once the notification is /// destroyed (its generation moves on) the target is dead. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Target { pub notification: NotificationId, pub generation: Generation, pub badge: Badge, } pub struct Timers { deadlines: [Option<(Ticks, Target)>; MAX_PROCESSES], } impl Timers { pub const fn new() -> Self { Self { deadlines: [None; MAX_PROCESSES], } } /// Replaces `owner`'s timer. pub fn set(&mut self, owner: ProcessId, deadline: Ticks, target: Target) -> bool { match self.deadlines.get_mut(owner.raw() as usize) { Some(slot) => { *slot = Some((deadline, target)); true } None => false, } } pub fn clear(&mut self, owner: ProcessId) { if let Some(slot) = self.deadlines.get_mut(owner.raw() as usize) { *slot = None; } } /// Removes and returns one timer whose deadline is at or before `now`. pub fn take_expired(&mut self, now: Ticks) -> Option { let slot = self .deadlines .iter_mut() .find(|s| s.is_some_and(|(d, _)| d <= now))?; slot.take().map(|(_, t)| t) } pub fn earliest(&self) -> Option { self.deadlines.iter().flatten().map(|(d, _)| *d).min() } } impl Default for Timers { fn default() -> Self { Self::new() } }