sparreal_kernel/time/
mod.rs1use core::time::Duration;
2
3use crate::{
4 globals::{cpu_global, cpu_global_meybeuninit, cpu_global_mut},
5 irq::{IrqHandleResult, IrqParam},
6};
7
8use rdrive::{Device, DeviceGuard, intc::IrqId};
9pub use timer::Timer;
10
11mod queue;
12mod timer;
13
14#[derive(Default)]
15pub(crate) struct TimerData {
16 timer: Option<Device<Timer>>,
17}
18
19pub fn since_boot() -> Duration {
20 _since_boot().unwrap_or_default()
21}
22
23fn _since_boot() -> Option<Duration> {
24 let timer = cpu_global_meybeuninit()?.timer.timer.as_ref()?;
25 Some(timer.since_boot())
26}
27
28pub(crate) fn init_current_cpu() -> Option<()> {
29 {
30 let mut ls = rdrive::read(|m| m.timer.all());
31 let (_, timer) = ls.pop()?;
32
33 let mut timer = timer.upgrade()?.spin_try_borrow_by(0.into());
34
35 unsafe {
36 cpu_global_mut().timer.timer = Some(Device::new(
37 timer.descriptor.clone(),
38 Timer::new(timer.get_current_cpu()),
39 ))
40 };
41 }
42 let mut t = timer_write()?;
43
44 t.set_irq_enable(false);
45 t.enable();
46
47 IrqParam {
48 intc: t.descriptor.irq_parent?,
49 cfg: t.irq(),
50 }
51 .register_builder(irq_handle)
52 .register();
53
54 Some(())
55}
56
57fn timer_write() -> Option<DeviceGuard<Timer>> {
58 Some(timer_data().timer.as_ref()?.spin_try_borrow_by(0.into()))
59}
60fn irq_handle(_irq: IrqId) -> IrqHandleResult {
61 let t = unsafe { &mut *timer_data().timer.as_ref().unwrap().force_use() };
62 t.handle_irq();
63 IrqHandleResult::Handled
64}
65
66fn timer_data() -> &'static TimerData {
67 &cpu_global().timer
68}
69
70pub fn after(duration: Duration, call: impl Fn() + 'static) {
71 if let Some(mut t) = timer_write() {
72 t.after(duration, call);
73 }
74}
75
76pub fn spin_delay(duration: Duration) {
77 let now = since_boot();
78 let at = now + duration;
79
80 loop {
81 if since_boot() >= at {
82 break;
83 }
84 }
85}
86
87pub fn sleep(duration: Duration) {
88 let pid = crate::task::current().pid;
89 after(duration, move || {
90 crate::task::wake_up_in_irq(pid);
91 });
92 crate::task::suspend();
93}