sparreal_kernel/os/time/
timer.rs1use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
2use core::{
3 sync::atomic::{AtomicBool, Ordering},
4 time::Duration,
5};
6
7use super::{duration_to_ticks, ticks};
8use crate::os::sync::IrqSpinlock;
9
10type TimerCallback = Box<dyn FnMut() + Send + 'static>;
11
12static TIMER_MANAGER: IrqSpinlock<Option<TimerManager>> = IrqSpinlock::new(None);
13static TIMER_READY: AtomicBool = AtomicBool::new(false);
14
15pub type TimerResult<T> = core::result::Result<T, TimerError>;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum TimerError {
19 NotReady,
20 Overflow,
21}
22
23#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
24pub struct TimerHandle(TimerId);
25
26impl TimerHandle {
27 pub fn cancel(self) -> bool {
28 cancel(self)
29 }
30}
31
32#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
33struct TimerId(u64);
34
35#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
36struct TimerKey {
37 deadline: usize,
39 id: TimerId,
40}
41
42#[derive(Debug, Clone, Copy)]
43pub struct TimeListEntry {
44 pub handle: TimerHandle,
45 pub deadline: usize,
46 pub remaining: usize,
47}
48
49struct TimerManager {
52 next_id: u64,
53 timers: BTreeMap<TimerKey, TimerCallback>,
54 index: BTreeMap<TimerId, usize>,
55}
56
57impl TimerManager {
58 fn new() -> Self {
59 Self {
60 next_id: 1,
61 timers: BTreeMap::new(),
62 index: BTreeMap::new(),
63 }
64 }
65
66 fn schedule_after<F>(&mut self, delay: usize, callback: F) -> TimerResult<TimerHandle>
67 where
68 F: FnOnce() + Send + 'static,
69 {
70 let now = ticks();
71 let deadline = now.checked_add(delay).ok_or(TimerError::Overflow)?;
72 Ok(self.schedule_at_internal(deadline, callback))
73 }
74
75 fn schedule_at<F>(&mut self, deadline: usize, callback: F) -> TimerHandle
76 where
77 F: FnOnce() + Send + 'static,
78 {
79 self.schedule_at_internal(deadline, callback)
80 }
81
82 fn schedule_at_internal<F>(&mut self, deadline: usize, callback: F) -> TimerHandle
83 where
84 F: FnOnce() + Send + 'static,
85 {
86 let id = self.next_timer_id();
87 let key = TimerKey { deadline, id };
88
89 let is_earliest = self
91 .timers
92 .keys()
93 .next()
94 .is_none_or(|k| deadline < k.deadline);
95
96 self.timers.insert(key, into_callback(callback));
97
98 self.index.insert(id, deadline);
99 if is_earliest {
102 self.arm_hardware_timer();
103 }
104
105 TimerHandle(id)
106 }
107
108 fn cancel(&mut self, handle: TimerHandle) -> bool {
109 if let Some(deadline) = self.index.remove(&handle.0) {
110 let key = TimerKey {
111 deadline,
112 id: handle.0,
113 };
114 let was_first = self.timers.keys().next().is_some_and(|k| *k == key);
115 self.timers.remove(&key);
116
117 if was_first {
119 self.arm_hardware_timer();
120 }
121 return true;
122 }
123 false
124 }
125
126 fn handle_irq(&mut self) -> Vec<TimerCallback> {
127 let now = ticks();
128 let mut expired = Vec::new();
129
130 while let Some(key) = self.timers.keys().next().cloned() {
132 if key.deadline > now {
133 break;
134 }
135 if let Some(cb) = self.timers.remove(&key) {
136 expired.push(cb);
137 }
138 self.index.remove(&key.id);
139 }
140
141 self.arm_hardware_timer();
143
144 expired
145 }
146
147 fn arm_hardware_timer(&self) {
149 if let Some(key) = self.timers.keys().next() {
150 let now = ticks();
151 let delay = key.deadline.saturating_sub(now);
152
153 let delay = delay.max(1);
156
157 crate::hal::al::cpu::systick_set_interval(delay);
158 crate::hal::al::cpu::systick_irq_enable();
159 } else {
160 crate::hal::al::cpu::systick_set_interval(usize::MAX);
162 crate::hal::al::cpu::systick_irq_disable();
163 }
164 }
165
166 fn snapshot(&self) -> Vec<TimeListEntry> {
167 let now = ticks();
168 let mut list = Vec::with_capacity(self.timers.len());
169 for key in self.timers.keys() {
170 let remaining = key.deadline.saturating_sub(now);
171 list.push(TimeListEntry {
172 handle: TimerHandle(key.id),
173 deadline: key.deadline,
174 remaining,
175 });
176 }
177 list
178 }
179
180 fn next_timer_id(&mut self) -> TimerId {
185 loop {
186 let id = TimerId(self.next_id);
187 self.next_id = self.next_id.wrapping_add(1);
188 if !self.index.contains_key(&id) {
189 return id;
190 }
191 }
192 }
193}
194
195pub(crate) fn init() {
196 {
197 let mut guard = TIMER_MANAGER.lock();
198 if guard.is_some() {
199 return;
200 }
201 *guard = Some(TimerManager::new());
202 }
203
204 TIMER_READY.store(true, Ordering::Release);
205
206 let timer_irq = crate::hal::al::cpu::systick_irq_id();
207 crate::os::irq::register_handler(timer_irq, systimer_irq_handler);
208}
209
210pub fn one_shot_after<F>(delay: Duration, callback: F) -> Result<TimerHandle, TimerError>
212where
213 F: FnOnce() + Send + 'static,
214{
215 if !is_ready() {
216 return Err(TimerError::NotReady);
217 }
218 let delay = duration_to_ticks(delay);
219 with_manager_mut(move |mgr| mgr.schedule_after(delay, callback)).ok_or(TimerError::NotReady)?
220}
221
222pub fn one_shot_at<F>(deadline: Duration, callback: F) -> Result<TimerHandle, TimerError>
224where
225 F: FnOnce() + Send + 'static,
226{
227 if !is_ready() {
228 return Err(TimerError::NotReady);
229 }
230 let mut cb = Some(callback);
231 let deadline = duration_to_ticks(deadline);
232 with_manager_mut(|mgr| mgr.schedule_at(deadline, cb.take().unwrap()))
233 .ok_or(TimerError::NotReady)
234}
235
236pub fn cancel(handle: TimerHandle) -> bool {
238 with_manager_mut(|mgr| mgr.cancel(handle)).unwrap_or(false)
239}
240
241pub fn time_list() -> Vec<TimeListEntry> {
243 with_manager(|mgr| mgr.snapshot()).unwrap_or_default()
244}
245
246pub fn is_ready() -> bool {
248 TIMER_READY.load(Ordering::Acquire)
249}
250
251fn systimer_irq_handler() {
252 crate::hal::al::cpu::systick_ack();
254 let callbacks = with_manager_mut(|mgr| mgr.handle_irq()).unwrap_or_default();
255 run_callbacks(callbacks);
256}
257
258fn run_callbacks(callbacks: Vec<TimerCallback>) {
259 for mut cb in callbacks {
260 (cb)();
261 }
262}
263
264fn into_callback<F>(f: F) -> TimerCallback
265where
266 F: FnOnce() + Send + 'static,
267{
268 let mut opt = Some(f);
269 Box::new(move || {
270 if let Some(inner) = opt.take() {
271 inner();
272 }
273 })
274}
275
276fn with_manager<F, R>(f: F) -> Option<R>
277where
278 F: FnOnce(&TimerManager) -> R,
279{
280 let guard = TIMER_MANAGER.lock();
281 guard.as_ref().map(f)
282}
283
284fn with_manager_mut<F, R>(f: F) -> Option<R>
285where
286 F: FnOnce(&mut TimerManager) -> R,
287{
288 let mut guard = TIMER_MANAGER.lock();
289 guard.as_mut().map(f)
290}