xref: /DragonOS/kernel/src/time/timer.rs (revision a30434f5201ca4c60b9515c8c23444fea3b5a8c6)
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     collections::LinkedList,
10     sync::{Arc, Weak},
11 };
12 
13 use crate::{
14     arch::{asm::current::current_pcb, sched::sched, CurrentIrqArch},
15     exception::{
16         softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
17         InterruptArch,
18     },
19     include::bindings::bindings::{process_control_block, process_wakeup, PROC_RUNNING},
20     kdebug, kerror, kinfo,
21     libs::spinlock::SpinLock,
22     syscall::SystemError,
23 };
24 
25 use super::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<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::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: &'static mut process_control_block,
44 }
45 
46 impl WakeUpHelper {
47     pub fn new(pcb: &'static mut process_control_block) -> Box<WakeUpHelper> {
48         return Box::new(WakeUpHelper { pcb });
49     }
50 }
51 
52 impl TimerFunction for WakeUpHelper {
53     fn run(&mut self) -> Result<(), SystemError> {
54         unsafe {
55             process_wakeup(self.pcb);
56         }
57         return Ok(());
58     }
59 }
60 
61 #[derive(Debug)]
62 pub struct Timer(SpinLock<InnerTimer>);
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(SpinLock::new(InnerTimer {
74             expire_jiffies,
75             timer_func,
76             self_ref: Weak::default(),
77         })));
78 
79         result.0.lock().self_ref = Arc::downgrade(&result);
80 
81         return result;
82     }
83 
84     /// @brief 将定时器插入到定时器链表中
85     pub fn activate(&self) {
86         let inner_guard = self.0.lock();
87         let timer_list = &mut TIMER_LIST.lock();
88 
89         // 链表为空,则直接插入
90         if timer_list.is_empty() {
91             // FIXME push_timer
92 
93             timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
94 
95             drop(inner_guard);
96             drop(timer_list);
97             compiler_fence(Ordering::SeqCst);
98 
99             return;
100         }
101         let mut split_pos: usize = 0;
102         for (pos, elt) in timer_list.iter().enumerate() {
103             if elt.0.lock().expire_jiffies > inner_guard.expire_jiffies {
104                 split_pos = pos;
105                 break;
106             }
107         }
108         let mut temp_list: LinkedList<Arc<Timer>> = timer_list.split_off(split_pos);
109         timer_list.push_back(inner_guard.self_ref.upgrade().unwrap());
110         timer_list.append(&mut temp_list);
111         drop(inner_guard);
112         drop(timer_list);
113     }
114 
115     #[inline]
116     fn run(&self) {
117         let r = self.0.lock().timer_func.run();
118         if unlikely(r.is_err()) {
119             kerror!(
120                 "Failed to run timer function: {self:?} {:?}",
121                 r.err().unwrap()
122             );
123         }
124     }
125 }
126 
127 /// 定时器类型
128 #[derive(Debug)]
129 pub struct InnerTimer {
130     /// 定时器结束时刻
131     pub expire_jiffies: u64,
132     /// 定时器需要执行的函数结构体
133     pub timer_func: Box<dyn TimerFunction>,
134     /// self_ref
135     self_ref: Weak<Timer>,
136 }
137 
138 #[derive(Debug)]
139 pub struct DoTimerSoftirq {
140     running: AtomicBool,
141 }
142 
143 impl DoTimerSoftirq {
144     pub fn new() -> Self {
145         return DoTimerSoftirq {
146             running: AtomicBool::new(false),
147         };
148     }
149 
150     fn set_run(&self) -> bool {
151         let x = self
152             .running
153             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
154         if x.is_ok() {
155             return true;
156         } else {
157             return false;
158         }
159     }
160 
161     fn clear_run(&self) {
162         self.running.store(false, Ordering::Release);
163     }
164 }
165 impl SoftirqVec for DoTimerSoftirq {
166     fn run(&self) {
167         if self.set_run() == false {
168             return;
169         }
170         // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器
171         for _ in 0..TIMER_RUN_CYCLE_THRESHOLD {
172             // kdebug!("DoTimerSoftirq run");
173             let timer_list = TIMER_LIST.try_lock();
174             if timer_list.is_err() {
175                 continue;
176             }
177             let mut timer_list = timer_list.unwrap();
178 
179             if timer_list.is_empty() {
180                 break;
181             }
182 
183             let timer_list_front = timer_list.pop_front().unwrap();
184             // kdebug!("to lock timer_list_front");
185             let mut timer_list_front_guard = None;
186             for _ in 0..10 {
187                 let x = timer_list_front.0.try_lock();
188                 if x.is_err() {
189                     continue;
190                 }
191                 timer_list_front_guard = Some(x.unwrap());
192             }
193             if timer_list_front_guard.is_none() {
194                 continue;
195             }
196             let timer_list_front_guard = timer_list_front_guard.unwrap();
197             if timer_list_front_guard.expire_jiffies > TIMER_JIFFIES.load(Ordering::SeqCst) {
198                 drop(timer_list_front_guard);
199                 timer_list.push_front(timer_list_front);
200                 break;
201             }
202             drop(timer_list_front_guard);
203             drop(timer_list);
204             timer_list_front.run();
205         }
206 
207         self.clear_run();
208     }
209 }
210 
211 /// @brief 初始化timer模块
212 pub fn timer_init() {
213     // FIXME 调用register_trap
214     let do_timer_softirq = Arc::new(DoTimerSoftirq::new());
215     softirq_vectors()
216         .register_softirq(SoftirqNumber::TIMER, do_timer_softirq)
217         .expect("Failed to register timer softirq");
218     kinfo!("timer initialized successfully");
219 }
220 
221 /// 计算接下来n毫秒对应的定时器时间片
222 pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
223     return TIMER_JIFFIES.load(Ordering::SeqCst) + 1000 * (expire_ms);
224 }
225 /// 计算接下来n微秒对应的定时器时间片
226 pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
227     return TIMER_JIFFIES.load(Ordering::SeqCst) + (expire_us);
228 }
229 
230 /// @brief 让pcb休眠timeout个jiffies
231 ///
232 /// @param timeout 需要休眠的时间(单位:jiffies)
233 ///
234 /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies)
235 ///
236 /// @return Err(SystemError) 错误码
237 pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
238     // kdebug!("schedule_timeout");
239     if timeout == MAX_TIMEOUT {
240         sched();
241         return Ok(MAX_TIMEOUT);
242     } else if timeout < 0 {
243         kerror!("timeout can't less than 0");
244         return Err(SystemError::EINVAL);
245     } else {
246         // 禁用中断,防止在这段期间发生调度,造成死锁
247         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
248 
249         timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
250         let timer = Timer::new(WakeUpHelper::new(current_pcb()), timeout as u64);
251         timer.activate();
252         current_pcb().state &= (!PROC_RUNNING) as u64;
253 
254         drop(irq_guard);
255 
256         sched();
257         let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
258         if time_remaining >= 0 {
259             // 被提前唤醒,返回剩余时间
260             return Ok(time_remaining);
261         } else {
262             return Ok(0);
263         }
264     }
265 }
266 
267 pub fn timer_get_first_expire() -> Result<u64, SystemError> {
268     // FIXME
269     // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
270     for _ in 0..10 {
271         match TIMER_LIST.try_lock() {
272             Ok(timer_list) => {
273                 // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
274                 if timer_list.is_empty() {
275                     // kdebug!("timer_list is empty");
276                     return Ok(0);
277                 } else {
278                     // kdebug!("timer_list not empty");
279                     return Ok(timer_list.front().unwrap().0.lock().expire_jiffies);
280                 }
281             }
282             // 加锁失败返回啥??
283             Err(_) => continue,
284         }
285     }
286     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
287 }
288 
289 pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
290     let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
291     compiler_fence(Ordering::SeqCst);
292     update_wall_time();
293 
294     compiler_fence(Ordering::SeqCst);
295     return prev + add_jiffies;
296 }
297 
298 pub fn clock() -> u64 {
299     return TIMER_JIFFIES.load(Ordering::SeqCst);
300 }
301 // ====== 重构完成后请删掉extern C ======
302 #[no_mangle]
303 pub extern "C" fn rs_clock() -> u64 {
304     clock()
305 }
306 
307 // ====== 以下为给C提供的接口 ======
308 #[no_mangle]
309 pub extern "C" fn rs_schedule_timeout(timeout: i64) -> i64 {
310     match schedule_timeout(timeout) {
311         Ok(v) => {
312             return v;
313         }
314         Err(e) => {
315             kdebug!("rs_schedule_timeout run failed");
316             return e.to_posix_errno() as i64;
317         }
318     }
319 }
320 
321 #[no_mangle]
322 pub extern "C" fn rs_timer_init() {
323     timer_init();
324 }
325 
326 #[no_mangle]
327 pub extern "C" fn rs_timer_next_n_ms_jiffies(expire_ms: u64) -> u64 {
328     return next_n_ms_timer_jiffies(expire_ms);
329 }
330 
331 #[no_mangle]
332 pub extern "C" fn rs_timer_next_n_us_jiffies(expire_us: u64) -> u64 {
333     return next_n_us_timer_jiffies(expire_us);
334 }
335 
336 #[no_mangle]
337 pub extern "C" fn rs_timer_get_first_expire() -> i64 {
338     match timer_get_first_expire() {
339         Ok(v) => return v as i64,
340         Err(_) => return 0,
341     }
342 }
343 
344 #[no_mangle]
345 pub extern "C" fn rs_update_timer_jiffies(add_jiffies: u64) -> u64 {
346     return update_timer_jiffies(add_jiffies);
347 }
348