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