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