sparreal_kernel/time/
mod.rs1use 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 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}