sparreal_kernel/time/
mod.rs

1use core::{
2    cell::UnsafeCell,
3    ops::{Deref, DerefMut},
4    time::Duration,
5};
6
7use crate::{
8    globals::{cpu_global, cpu_global_meybeuninit, cpu_global_mut},
9    irq::{IrqHandleResult, IrqParam},
10};
11
12use rdrive::IrqId;
13use spin::{Mutex, MutexGuard};
14pub use timer::Timer;
15
16mod queue;
17mod timer;
18
19#[derive(Default)]
20pub(crate) struct TimerData {
21    mutex: Mutex<()>,
22    timer: UnsafeCell<Option<Timer>>,
23}
24
25unsafe impl Sync for TimerData {}
26unsafe impl Send for TimerData {}
27
28pub(crate) struct Guard<'a> {
29    _guard: MutexGuard<'a, ()>,
30    timer: *mut Option<Timer>,
31    irq_state: bool,
32}
33
34impl Drop for Guard<'_> {
35    fn drop(&mut self) {
36        if let Some(t) = unsafe { &mut *self.timer } {
37            t.set_irq_enable(self.irq_state);
38        }
39    }
40}
41
42impl Deref for Guard<'_> {
43    type Target = Option<Timer>;
44
45    fn deref(&self) -> &Self::Target {
46        unsafe { &*self.timer }
47    }
48}
49
50impl DerefMut for Guard<'_> {
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        unsafe { &mut *self.timer }
53    }
54}
55
56impl TimerData {
57    pub fn lock<'a>(&'a self) -> Guard<'a> {
58        let timer = unsafe { &mut *self.timer.get() };
59        let mut irq_state = false;
60        if let Some(t) = timer {
61            irq_state = t.get_irq_status();
62            t.set_irq_enable(false);
63        }
64        let g = self.mutex.lock();
65        Guard {
66            _guard: g,
67            timer: timer as _,
68            irq_state,
69        }
70    }
71
72    fn force_use(&self) -> *mut Option<Timer> {
73        self.timer.get()
74    }
75}
76
77pub fn since_boot() -> Duration {
78    _since_boot().unwrap_or_default()
79}
80
81fn _since_boot() -> Option<Duration> {
82    let timer = unsafe { &*cpu_global_meybeuninit()?.timer.force_use() }.as_ref()?;
83    Some(timer.since_boot())
84}
85
86pub(crate) fn init_current_cpu() -> Option<()> {
87    let intc;
88    let cfg;
89    {
90        let systick = rdrive::get_one::<rdif_systick::Systick>().unwrap();
91        intc = systick.descriptor().irq_parent?;
92        let cpu_if = { systick.lock().unwrap().cpu_local() };
93        cfg = cpu_if.irq();
94        cpu_if.set_irq_enable(false);
95        let t = Timer::new(cpu_if);
96
97        unsafe { *cpu_global_mut().timer.lock() = Some(t) };
98    };
99    IrqParam { intc, cfg }
100        .register_builder(irq_handle)
101        .register();
102
103    Some(())
104}
105
106fn irq_handle(_irq: IrqId) -> IrqHandleResult {
107    let timer = unsafe { &mut *timer_data().force_use() };
108    if let Some(t) = timer.as_mut() {
109        t.handle_irq();
110    } else {
111        // Timer not initialized, do nothing
112        return IrqHandleResult::None;
113    }
114    IrqHandleResult::Handled
115}
116
117fn timer_data() -> &'static TimerData {
118    &cpu_global().timer
119}
120
121pub fn after(duration: Duration, call: impl Fn() + 'static) {
122    let mut g = timer_data().lock();
123    if let Some(t) = g.as_mut() {
124        t.after(duration, call);
125    }
126}
127
128pub fn spin_delay(duration: Duration) {
129    let now = since_boot();
130    let at = now + duration;
131
132    loop {
133        if since_boot() >= at {
134            break;
135        }
136    }
137}
138
139pub fn sleep(duration: Duration) {
140    let pid = crate::task::current().pid;
141    after(duration, move || {
142        crate::task::wake_up_in_irq(pid);
143    });
144    crate::task::suspend();
145}