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