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