sparreal_kernel/time/
mod.rs

1use 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}