xref: /DragonOS/kernel/src/time/timer.rs (revision dfe53cf087ef4c7b6db63d992906b062dc63e93f)
1 use core::{
2     fmt::Debug,
3     intrinsics::unlikely,
4     sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering},
5 };
6 
7 use alloc::{
8     boxed::Box,
9     sync::{Arc, Weak},
10     vec::Vec,
11 };
12 use system_error::SystemError;
13 
14 use crate::{
15     arch::{sched::sched, CurrentIrqArch},
16     exception::{
17         softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
18         InterruptArch,
19     },
20     kerror, kinfo,
21     libs::spinlock::{SpinLock, SpinLockGuard},
22     process::{ProcessControlBlock, ProcessManager},
23 };
24 
25 use super::{jiffies::NSEC_PER_JIFFY, timekeeping::update_wall_time};
26 
27 const MAX_TIMEOUT: i64 = i64::MAX;
28 const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
29 static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
30 
31 lazy_static! {
32     pub static ref TIMER_LIST: SpinLock<Vec<(u64, Arc<Timer>)>> = SpinLock::new(Vec::new());
33 }
34 
35 /// 定时器要执行的函数的特征
36 pub trait TimerFunction: Send + Sync + Debug {
37     fn run(&mut self) -> Result<(), SystemError>;
38 }
39 
40 #[derive(Debug)]
41 /// WakeUpHelper函数对应的结构体
42 pub struct WakeUpHelper {
43     pcb: Arc<ProcessControlBlock>,
44 }
45 
46 impl WakeUpHelper {
47     pub fn new(pcb: Arc<ProcessControlBlock>) -> Box<WakeUpHelper> {
48         return Box::new(WakeUpHelper { pcb });
49     }
50 }
51 
52 impl TimerFunction for WakeUpHelper {
53     fn run(&mut self) -> Result<(), SystemError> {
54         ProcessManager::wakeup(&self.pcb).ok();
55         return Ok(());
56     }
57 }
58 
59 #[derive(Debug)]
60 pub struct Timer {
61     inner: SpinLock<InnerTimer>,
62 }
63 
64 impl Timer {
65     /// @brief 创建一个定时器(单位:ms)
66     ///
67     /// @param timer_func 定时器需要执行的函数对应的结构体
68     ///
69     /// @param expire_jiffies 定时器结束时刻
70     ///
71     /// @return 定时器结构体
72     pub fn new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self> {
73         let result: Arc<Timer> = Arc::new(Timer {
74             inner: SpinLock::new(InnerTimer {
75                 expire_jiffies,
76                 timer_func: Some(timer_func),
77                 self_ref: Weak::default(),
78                 triggered: false,
79             }),
80         });
81 
82         result.inner.lock().self_ref = Arc::downgrade(&result);
83 
84         return result;
85     }
86 
87     pub fn inner(&self) -> SpinLockGuard<InnerTimer> {
88         return self.inner.lock_irqsave();
89     }
90 
91     /// @brief 将定时器插入到定时器链表中
92     pub fn activate(&self) {
93         let mut timer_list = TIMER_LIST.lock_irqsave();
94         let inner_guard = self.inner();
95 
96         // 链表为空,则直接插入
97         if timer_list.is_empty() {
98             // FIXME push_timer
99             timer_list.push((
100                 inner_guard.expire_jiffies,
101                 inner_guard.self_ref.upgrade().unwrap(),
102             ));
103 
104             drop(inner_guard);
105             drop(timer_list);
106             compiler_fence(Ordering::SeqCst);
107 
108             return;
109         }
110         let expire_jiffies = inner_guard.expire_jiffies;
111         let self_arc = inner_guard.self_ref.upgrade().unwrap();
112         drop(inner_guard);
113         let mut split_pos: usize = 0;
114         for (pos, elt) in timer_list.iter().enumerate() {
115             if Arc::ptr_eq(&self_arc, &elt.1) {
116                 kwarn!("Timer already in list");
117             }
118             if elt.0 > expire_jiffies {
119                 split_pos = pos;
120                 break;
121             }
122         }
123         timer_list.insert(split_pos, (expire_jiffies, self_arc));
124 
125         drop(timer_list);
126     }
127 
128     #[inline]
129     fn run(&self) {
130         let mut timer = self.inner();
131         timer.triggered = true;
132         let func = timer.timer_func.take();
133         drop(timer);
134         let r = func.map(|mut f| f.run()).unwrap_or(Ok(()));
135         if unlikely(r.is_err()) {
136             kerror!(
137                 "Failed to run timer function: {self:?} {:?}",
138                 r.as_ref().err().unwrap()
139             );
140         }
141     }
142 
143     /// ## 判断定时器是否已经触发
144     pub fn timeout(&self) -> bool {
145         self.inner().triggered
146     }
147 
148     /// ## 取消定时器任务
149     pub fn cancel(&self) -> bool {
150         let this_arc = self.inner().self_ref.upgrade().unwrap();
151         TIMER_LIST
152             .lock_irqsave()
153             .extract_if(|x| Arc::ptr_eq(&this_arc, &x.1))
154             .for_each(drop);
155         true
156     }
157 }
158 
159 /// 定时器类型
160 #[derive(Debug)]
161 pub struct InnerTimer {
162     /// 定时器结束时刻
163     pub expire_jiffies: u64,
164     /// 定时器需要执行的函数结构体
165     pub timer_func: Option<Box<dyn TimerFunction>>,
166     /// self_ref
167     self_ref: Weak<Timer>,
168     /// 判断该计时器是否触发
169     triggered: bool,
170 }
171 
172 #[derive(Debug)]
173 pub struct DoTimerSoftirq {
174     running: AtomicBool,
175 }
176 
177 impl DoTimerSoftirq {
178     pub fn new() -> Self {
179         return DoTimerSoftirq {
180             running: AtomicBool::new(false),
181         };
182     }
183 
184     fn set_run(&self) -> bool {
185         let x = self
186             .running
187             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
188         return x.is_ok();
189     }
190 
191     fn clear_run(&self) {
192         self.running.store(false, Ordering::Release);
193     }
194 }
195 impl SoftirqVec for DoTimerSoftirq {
196     fn run(&self) {
197         if !self.set_run() {
198             return;
199         }
200         // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器
201         for _ in 0..TIMER_RUN_CYCLE_THRESHOLD {
202             // kdebug!("DoTimerSoftirq run");
203             let timer_list = TIMER_LIST.try_lock_irqsave();
204             if timer_list.is_err() {
205                 continue;
206             }
207             let mut timer_list = timer_list.unwrap();
208 
209             if timer_list.is_empty() {
210                 break;
211             }
212 
213             let (front_jiffies, timer_list_front) = timer_list.first().unwrap().clone();
214             // kdebug!("to lock timer_list_front");
215 
216             if front_jiffies >= TIMER_JIFFIES.load(Ordering::SeqCst) {
217                 break;
218             }
219             timer_list.remove(0);
220             drop(timer_list);
221             timer_list_front.run();
222         }
223 
224         self.clear_run();
225     }
226 }
227 
228 /// 初始化系统定时器
229 #[inline(never)]
230 pub fn timer_init() {
231     // FIXME 调用register_trap
232     let do_timer_softirq = Arc::new(DoTimerSoftirq::new());
233     softirq_vectors()
234         .register_softirq(SoftirqNumber::TIMER, do_timer_softirq)
235         .expect("Failed to register timer softirq");
236     kinfo!("timer initialized successfully");
237 }
238 
239 /// 计算接下来n毫秒对应的定时器时间片
240 pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
241     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_ms * 1000000 / NSEC_PER_JIFFY as u64;
242 }
243 /// 计算接下来n微秒对应的定时器时间片
244 pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
245     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_us * 1000 / NSEC_PER_JIFFY as u64;
246 }
247 
248 /// @brief 让pcb休眠timeout个jiffies
249 ///
250 /// @param timeout 需要休眠的时间(单位:jiffies)
251 ///
252 /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies)
253 ///
254 /// @return Err(SystemError) 错误码
255 pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
256     // kdebug!("schedule_timeout");
257     if timeout == MAX_TIMEOUT {
258         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
259         ProcessManager::mark_sleep(true).ok();
260         drop(irq_guard);
261         sched();
262         return Ok(MAX_TIMEOUT);
263     } else if timeout < 0 {
264         kerror!("timeout can't less than 0");
265         return Err(SystemError::EINVAL);
266     } else {
267         // 禁用中断,防止在这段期间发生调度,造成死锁
268         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
269 
270         timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
271         let timer = Timer::new(
272             WakeUpHelper::new(ProcessManager::current_pcb()),
273             timeout as u64,
274         );
275         ProcessManager::mark_sleep(true).ok();
276         timer.activate();
277 
278         drop(irq_guard);
279 
280         sched();
281         let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
282         if time_remaining >= 0 {
283             // 被提前唤醒,返回剩余时间
284             return Ok(time_remaining);
285         } else {
286             return Ok(0);
287         }
288     }
289 }
290 
291 pub fn timer_get_first_expire() -> Result<u64, SystemError> {
292     // FIXME
293     // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
294     for _ in 0..10 {
295         match TIMER_LIST.try_lock_irqsave() {
296             Ok(timer_list) => {
297                 // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
298                 if timer_list.is_empty() {
299                     // kdebug!("timer_list is empty");
300                     return Ok(0);
301                 } else {
302                     // kdebug!("timer_list not empty");
303                     return Ok(timer_list.first().unwrap().0);
304                 }
305             }
306             // 加锁失败返回啥??
307             Err(_) => continue,
308         }
309     }
310     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
311 }
312 
313 /// 更新系统时间片
314 pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
315     let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
316     compiler_fence(Ordering::SeqCst);
317     update_wall_time(time_us);
318 
319     compiler_fence(Ordering::SeqCst);
320     return prev + add_jiffies;
321 }
322 
323 pub fn clock() -> u64 {
324     return TIMER_JIFFIES.load(Ordering::SeqCst);
325 }
326 
327 // ====== 以下为给C提供的接口 ======
328 
329 #[no_mangle]
330 pub extern "C" fn rs_timer_init() {
331     timer_init();
332 }
333