strat9_kernel/process/
timer.rs1use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(u32)]
14pub enum ITimerWhich {
15 Real = 0,
16 Virtual = 1,
17 Prof = 2,
18}
19
20impl ITimerWhich {
21 pub fn from_u32(value: u32) -> Option<Self> {
23 match value {
24 0 => Some(ITimerWhich::Real),
25 1 => Some(ITimerWhich::Virtual),
26 2 => Some(ITimerWhich::Prof),
27 _ => None,
28 }
29 }
30
31 pub fn signal(self) -> u32 {
33 match self {
34 ITimerWhich::Real => 14, ITimerWhich::Virtual => 26, ITimerWhich::Prof => 27, }
38 }
39}
40
41#[repr(C)]
43#[derive(Debug, Clone, Copy)]
44pub struct ITimerVal {
45 pub it_interval: TimeVal,
47 pub it_value: TimeVal,
49}
50
51impl ITimerVal {
52 pub const fn zero() -> Self {
54 Self {
55 it_interval: TimeVal::zero(),
56 it_value: TimeVal::zero(),
57 }
58 }
59
60 pub fn to_nanos(&self) -> (u64, u64) {
62 (self.it_interval.to_nanos(), self.it_value.to_nanos())
63 }
64}
65
66#[repr(C)]
68#[derive(Debug, Clone, Copy)]
69pub struct TimeVal {
70 pub tv_sec: i64,
71 pub tv_usec: i64,
72}
73
74impl TimeVal {
75 pub const fn zero() -> Self {
77 Self {
78 tv_sec: 0,
79 tv_usec: 0,
80 }
81 }
82
83 pub fn to_nanos(&self) -> u64 {
85 (self.tv_sec as u64)
86 .saturating_mul(1_000_000_000)
87 .saturating_add((self.tv_usec as u64).saturating_mul(1_000))
88 }
89
90 pub fn from_nanos(nanos: u64) -> Self {
92 let tv_sec = (nanos / 1_000_000_000) as i64;
93 let tv_usec = ((nanos % 1_000_000_000) / 1_000) as i64;
94 Self { tv_sec, tv_usec }
95 }
96}
97
98pub struct ITimerState {
100 next_expiration: AtomicU64,
102 interval_ns: AtomicU64,
104 armed: AtomicBool,
106}
107
108impl ITimerState {
109 pub const fn new() -> Self {
111 Self {
112 next_expiration: AtomicU64::new(0),
113 interval_ns: AtomicU64::new(0),
114 armed: AtomicBool::new(false),
115 }
116 }
117
118 pub fn get(&self, current_time_ns: u64) -> ITimerVal {
120 let next = self.next_expiration.load(Ordering::Relaxed);
121 let interval = self.interval_ns.load(Ordering::Relaxed);
122
123 let value_ns = if next > current_time_ns {
124 next - current_time_ns
125 } else {
126 0
127 };
128
129 ITimerVal {
130 it_interval: TimeVal::from_nanos(interval),
131 it_value: TimeVal::from_nanos(value_ns),
132 }
133 }
134
135 pub fn set(&self, value: &ITimerVal, current_time_ns: u64) {
137 let (interval_ns, value_ns) = value.to_nanos();
138
139 if value_ns == 0 {
140 self.armed.store(false, Ordering::Release);
141 self.next_expiration.store(0, Ordering::Relaxed);
142 self.interval_ns.store(interval_ns, Ordering::Relaxed);
143 } else {
144 self.interval_ns.store(interval_ns, Ordering::Relaxed);
145 let next = current_time_ns.saturating_add(value_ns);
146 self.next_expiration.store(next, Ordering::Relaxed);
147 self.armed.store(true, Ordering::Release);
148 }
149 }
150
151 pub fn check_expired(&self, current_time_ns: u64) -> bool {
153 if !self.armed.load(Ordering::Acquire) {
154 return false;
155 }
156
157 let next = self.next_expiration.load(Ordering::Relaxed);
158 if current_time_ns >= next && next != 0 {
159 let interval = self.interval_ns.load(Ordering::Relaxed);
160 if interval == 0 {
161 self.armed.store(false, Ordering::Release);
162 self.next_expiration.store(0, Ordering::Relaxed);
163 } else {
164 let new_next = next.saturating_add(interval);
166 let new_next = if new_next <= current_time_ns {
167 current_time_ns.saturating_add(interval)
168 } else {
169 new_next
170 };
171 self.next_expiration.store(new_next, Ordering::Relaxed);
172 }
173 true
174 } else {
175 false
176 }
177 }
178
179 pub fn disarm(&self) {
181 self.armed.store(false, Ordering::Release);
182 self.next_expiration.store(0, Ordering::Relaxed);
183 self.interval_ns.store(0, Ordering::Relaxed);
184 }
185}
186
187pub struct ITimers {
189 pub real: ITimerState,
190 pub virtual_timer: ITimerState,
191 pub prof: ITimerState,
192}
193
194impl ITimers {
195 pub const fn new() -> Self {
197 Self {
198 real: ITimerState::new(),
199 virtual_timer: ITimerState::new(),
200 prof: ITimerState::new(),
201 }
202 }
203
204 pub fn get(&self, which: ITimerWhich) -> &ITimerState {
206 match which {
207 ITimerWhich::Real => &self.real,
208 ITimerWhich::Virtual => &self.virtual_timer,
209 ITimerWhich::Prof => &self.prof,
210 }
211 }
212
213 pub fn check_all(&self, current_time_ns: u64) -> alloc::vec::Vec<(ITimerWhich, u32)> {
216 use alloc::vec::Vec;
217 let mut expired = Vec::new();
218
219 if self.real.check_expired(current_time_ns) {
220 expired.push((ITimerWhich::Real, ITimerWhich::Real.signal()));
221 }
222 if self.virtual_timer.check_expired(current_time_ns) {
223 expired.push((ITimerWhich::Virtual, ITimerWhich::Virtual.signal()));
224 }
225 if self.prof.check_expired(current_time_ns) {
226 expired.push((ITimerWhich::Prof, ITimerWhich::Prof.signal()));
227 }
228
229 expired
230 }
231}
232
233pub fn tick_all_timers(current_time_ns: u64) {
240 use crate::process::{scheduler::SCHEDULER, signal::Signal};
241
242 let scheduler = match SCHEDULER.try_lock() {
243 Some(guard) => guard,
244 None => return,
245 };
246 let Some(ref sched) = *scheduler else { return };
247
248 for (_, task) in sched.all_tasks.iter() {
249 for which in [ITimerWhich::Real, ITimerWhich::Virtual, ITimerWhich::Prof] {
250 if task.itimers.get(which).check_expired(current_time_ns) {
251 if let Some(sig) = Signal::from_u32(which.signal()) {
252 task.pending_signals.add(sig);
253 }
254 }
255 }
256 }
257}