xref: /DragonOS/kernel/src/time/timer.rs (revision f0c87a897fe813b7f06bf5a9e93c43ad9519dafd)
136fd0130Shoumkh use core::{
236fd0130Shoumkh     fmt::Debug,
336fd0130Shoumkh     intrinsics::unlikely,
436fd0130Shoumkh     sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering},
536fd0130Shoumkh };
6bacd691cSlogin 
7bacd691cSlogin use alloc::{
8bacd691cSlogin     boxed::Box,
9bacd691cSlogin     sync::{Arc, Weak},
10b8ed3825SDonkey Kane     vec::Vec,
11bacd691cSlogin };
1291e9d4abSLoGin use system_error::SystemError;
13bacd691cSlogin 
14bacd691cSlogin use crate::{
15*f0c87a89SGnoCiYeH     arch::CurrentIrqArch,
1636fd0130Shoumkh     exception::{
1736fd0130Shoumkh         softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
1836fd0130Shoumkh         InterruptArch,
19bacd691cSlogin     },
20be8cdf4bSLoGin     kerror, kinfo,
210d6cf65aSLoGin     libs::spinlock::{SpinLock, SpinLockGuard},
221496ba7bSLoGin     process::{ProcessControlBlock, ProcessManager},
23*f0c87a89SGnoCiYeH     sched::{schedule, SchedMode},
24bacd691cSlogin };
25bacd691cSlogin 
26b8ed3825SDonkey Kane use super::{jiffies::NSEC_PER_JIFFY, timekeeping::update_wall_time};
2736fd0130Shoumkh 
28bacd691cSlogin const MAX_TIMEOUT: i64 = i64::MAX;
29bacd691cSlogin const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
3036fd0130Shoumkh static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
31bacd691cSlogin 
32bacd691cSlogin lazy_static! {
33b8ed3825SDonkey Kane     pub static ref TIMER_LIST: SpinLock<Vec<(u64, Arc<Timer>)>> = SpinLock::new(Vec::new());
34bacd691cSlogin }
35bacd691cSlogin 
36bacd691cSlogin /// 定时器要执行的函数的特征
3736fd0130Shoumkh pub trait TimerFunction: Send + Sync + Debug {
3836fd0130Shoumkh     fn run(&mut self) -> Result<(), SystemError>;
39bacd691cSlogin }
40bacd691cSlogin 
4136fd0130Shoumkh #[derive(Debug)]
42bacd691cSlogin /// WakeUpHelper函数对应的结构体
43bacd691cSlogin pub struct WakeUpHelper {
441496ba7bSLoGin     pcb: Arc<ProcessControlBlock>,
45bacd691cSlogin }
46bacd691cSlogin 
47bacd691cSlogin impl WakeUpHelper {
481496ba7bSLoGin     pub fn new(pcb: Arc<ProcessControlBlock>) -> Box<WakeUpHelper> {
49bacd691cSlogin         return Box::new(WakeUpHelper { pcb });
50bacd691cSlogin     }
51bacd691cSlogin }
52bacd691cSlogin 
53bacd691cSlogin impl TimerFunction for WakeUpHelper {
5436fd0130Shoumkh     fn run(&mut self) -> Result<(), SystemError> {
551496ba7bSLoGin         ProcessManager::wakeup(&self.pcb).ok();
5636fd0130Shoumkh         return Ok(());
57bacd691cSlogin     }
58bacd691cSlogin }
59bacd691cSlogin 
6036fd0130Shoumkh #[derive(Debug)]
610d6cf65aSLoGin pub struct Timer {
620d6cf65aSLoGin     inner: SpinLock<InnerTimer>,
630d6cf65aSLoGin }
64bacd691cSlogin 
65bacd691cSlogin impl Timer {
66bacd691cSlogin     /// @brief 创建一个定时器(单位:ms)
67bacd691cSlogin     ///
68bacd691cSlogin     /// @param timer_func 定时器需要执行的函数对应的结构体
69bacd691cSlogin     ///
70bacd691cSlogin     /// @param expire_jiffies 定时器结束时刻
71bacd691cSlogin     ///
72bacd691cSlogin     /// @return 定时器结构体
73bacd691cSlogin     pub fn new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self> {
740d6cf65aSLoGin         let result: Arc<Timer> = Arc::new(Timer {
750d6cf65aSLoGin             inner: SpinLock::new(InnerTimer {
76bacd691cSlogin                 expire_jiffies,
770d6cf65aSLoGin                 timer_func: Some(timer_func),
78bacd691cSlogin                 self_ref: Weak::default(),
79971462beSGnoCiYeH                 triggered: false,
800d6cf65aSLoGin             }),
810d6cf65aSLoGin         });
82bacd691cSlogin 
830d6cf65aSLoGin         result.inner.lock().self_ref = Arc::downgrade(&result);
84bacd691cSlogin 
85bacd691cSlogin         return result;
86bacd691cSlogin     }
87bacd691cSlogin 
880d6cf65aSLoGin     pub fn inner(&self) -> SpinLockGuard<InnerTimer> {
890d6cf65aSLoGin         return self.inner.lock_irqsave();
900d6cf65aSLoGin     }
910d6cf65aSLoGin 
92bacd691cSlogin     /// @brief 将定时器插入到定时器链表中
93bacd691cSlogin     pub fn activate(&self) {
940d6cf65aSLoGin         let mut timer_list = TIMER_LIST.lock_irqsave();
950d6cf65aSLoGin         let inner_guard = self.inner();
96cde5492fSlogin 
97bacd691cSlogin         // 链表为空,则直接插入
98bacd691cSlogin         if timer_list.is_empty() {
99bacd691cSlogin             // FIXME push_timer
100b8ed3825SDonkey Kane             timer_list.push((
101b8ed3825SDonkey Kane                 inner_guard.expire_jiffies,
102b8ed3825SDonkey Kane                 inner_guard.self_ref.upgrade().unwrap(),
103b8ed3825SDonkey Kane             ));
104cde5492fSlogin 
105cde5492fSlogin             drop(inner_guard);
106cde5492fSlogin             drop(timer_list);
107cde5492fSlogin             compiler_fence(Ordering::SeqCst);
108cde5492fSlogin 
109bacd691cSlogin             return;
110bacd691cSlogin         }
111b8ed3825SDonkey Kane         let expire_jiffies = inner_guard.expire_jiffies;
112b8ed3825SDonkey Kane         let self_arc = inner_guard.self_ref.upgrade().unwrap();
113b8ed3825SDonkey Kane         drop(inner_guard);
114bacd691cSlogin         let mut split_pos: usize = 0;
115bacd691cSlogin         for (pos, elt) in timer_list.iter().enumerate() {
116b8ed3825SDonkey Kane             if Arc::ptr_eq(&self_arc, &elt.1) {
117b8ed3825SDonkey Kane                 kwarn!("Timer already in list");
118b8ed3825SDonkey Kane             }
119b8ed3825SDonkey Kane             if elt.0 > expire_jiffies {
120bacd691cSlogin                 split_pos = pos;
121bacd691cSlogin                 break;
122bacd691cSlogin             }
123bacd691cSlogin         }
124b8ed3825SDonkey Kane         timer_list.insert(split_pos, (expire_jiffies, self_arc));
125b8ed3825SDonkey Kane 
126cde5492fSlogin         drop(timer_list);
127bacd691cSlogin     }
128bacd691cSlogin 
129bacd691cSlogin     #[inline]
130bacd691cSlogin     fn run(&self) {
1310d6cf65aSLoGin         let mut timer = self.inner();
132971462beSGnoCiYeH         timer.triggered = true;
1330d6cf65aSLoGin         let func = timer.timer_func.take();
1340d6cf65aSLoGin         drop(timer);
1350d6cf65aSLoGin         let r = func.map(|mut f| f.run()).unwrap_or(Ok(()));
13636fd0130Shoumkh         if unlikely(r.is_err()) {
13736fd0130Shoumkh             kerror!(
13836fd0130Shoumkh                 "Failed to run timer function: {self:?} {:?}",
1398d72b68dSJomo                 r.as_ref().err().unwrap()
14036fd0130Shoumkh             );
14136fd0130Shoumkh         }
142bacd691cSlogin     }
143971462beSGnoCiYeH 
144971462beSGnoCiYeH     /// ## 判断定时器是否已经触发
145971462beSGnoCiYeH     pub fn timeout(&self) -> bool {
1460d6cf65aSLoGin         self.inner().triggered
147971462beSGnoCiYeH     }
148971462beSGnoCiYeH 
149971462beSGnoCiYeH     /// ## 取消定时器任务
150971462beSGnoCiYeH     pub fn cancel(&self) -> bool {
1510d6cf65aSLoGin         let this_arc = self.inner().self_ref.upgrade().unwrap();
152971462beSGnoCiYeH         TIMER_LIST
1530d6cf65aSLoGin             .lock_irqsave()
154b8ed3825SDonkey Kane             .extract_if(|x| Arc::ptr_eq(&this_arc, &x.1))
155840045afSLoGin             .for_each(drop);
156971462beSGnoCiYeH         true
157971462beSGnoCiYeH     }
158bacd691cSlogin }
159bacd691cSlogin 
160bacd691cSlogin /// 定时器类型
16136fd0130Shoumkh #[derive(Debug)]
162bacd691cSlogin pub struct InnerTimer {
163bacd691cSlogin     /// 定时器结束时刻
164bacd691cSlogin     pub expire_jiffies: u64,
165bacd691cSlogin     /// 定时器需要执行的函数结构体
1660d6cf65aSLoGin     pub timer_func: Option<Box<dyn TimerFunction>>,
167bacd691cSlogin     /// self_ref
168bacd691cSlogin     self_ref: Weak<Timer>,
169971462beSGnoCiYeH     /// 判断该计时器是否触发
170971462beSGnoCiYeH     triggered: bool,
171bacd691cSlogin }
172bacd691cSlogin 
173bacd691cSlogin #[derive(Debug)]
174bacd691cSlogin pub struct DoTimerSoftirq {
175bacd691cSlogin     running: AtomicBool,
176bacd691cSlogin }
177bacd691cSlogin 
178bacd691cSlogin impl DoTimerSoftirq {
179bacd691cSlogin     pub fn new() -> Self {
180bacd691cSlogin         return DoTimerSoftirq {
181bacd691cSlogin             running: AtomicBool::new(false),
182bacd691cSlogin         };
183bacd691cSlogin     }
184bacd691cSlogin 
185bacd691cSlogin     fn set_run(&self) -> bool {
186bacd691cSlogin         let x = self
187bacd691cSlogin             .running
188bacd691cSlogin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
189840045afSLoGin         return x.is_ok();
190bacd691cSlogin     }
191bacd691cSlogin 
192bacd691cSlogin     fn clear_run(&self) {
193bacd691cSlogin         self.running.store(false, Ordering::Release);
194bacd691cSlogin     }
195bacd691cSlogin }
196bacd691cSlogin impl SoftirqVec for DoTimerSoftirq {
197bacd691cSlogin     fn run(&self) {
198840045afSLoGin         if !self.set_run() {
199bacd691cSlogin             return;
200bacd691cSlogin         }
201bacd691cSlogin         // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器
202bacd691cSlogin         for _ in 0..TIMER_RUN_CYCLE_THRESHOLD {
203bacd691cSlogin             // kdebug!("DoTimerSoftirq run");
2040d6cf65aSLoGin             let timer_list = TIMER_LIST.try_lock_irqsave();
205cde5492fSlogin             if timer_list.is_err() {
206cde5492fSlogin                 continue;
207cde5492fSlogin             }
208cde5492fSlogin             let mut timer_list = timer_list.unwrap();
209bacd691cSlogin 
210bacd691cSlogin             if timer_list.is_empty() {
211bacd691cSlogin                 break;
212bacd691cSlogin             }
213bacd691cSlogin 
214b8ed3825SDonkey Kane             let (front_jiffies, timer_list_front) = timer_list.first().unwrap().clone();
215cde5492fSlogin             // kdebug!("to lock timer_list_front");
216b8ed3825SDonkey Kane 
217b8ed3825SDonkey Kane             if front_jiffies >= TIMER_JIFFIES.load(Ordering::SeqCst) {
218cde5492fSlogin                 break;
219cde5492fSlogin             }
220b8ed3825SDonkey Kane             timer_list.remove(0);
221cde5492fSlogin             drop(timer_list);
222cde5492fSlogin             timer_list_front.run();
223bacd691cSlogin         }
224bacd691cSlogin 
225bacd691cSlogin         self.clear_run();
226bacd691cSlogin     }
227bacd691cSlogin }
228bacd691cSlogin 
2295b59005fSLoGin /// 初始化系统定时器
2305b59005fSLoGin #[inline(never)]
231bacd691cSlogin pub fn timer_init() {
232bacd691cSlogin     // FIXME 调用register_trap
233bacd691cSlogin     let do_timer_softirq = Arc::new(DoTimerSoftirq::new());
234bacd691cSlogin     softirq_vectors()
235bacd691cSlogin         .register_softirq(SoftirqNumber::TIMER, do_timer_softirq)
236bacd691cSlogin         .expect("Failed to register timer softirq");
23740fe15e0SLoGin     kinfo!("timer initialized successfully");
238bacd691cSlogin }
239bacd691cSlogin 
240bacd691cSlogin /// 计算接下来n毫秒对应的定时器时间片
241bacd691cSlogin pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
242b8ed3825SDonkey Kane     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_ms * 1000000 / NSEC_PER_JIFFY as u64;
243bacd691cSlogin }
244bacd691cSlogin /// 计算接下来n微秒对应的定时器时间片
245bacd691cSlogin pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
246b8ed3825SDonkey Kane     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_us * 1000 / NSEC_PER_JIFFY as u64;
247bacd691cSlogin }
248bacd691cSlogin 
249bacd691cSlogin /// @brief 让pcb休眠timeout个jiffies
250bacd691cSlogin ///
251bacd691cSlogin /// @param timeout 需要休眠的时间(单位:jiffies)
252bacd691cSlogin ///
253bacd691cSlogin /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies)
254bacd691cSlogin ///
255bacd691cSlogin /// @return Err(SystemError) 错误码
256bacd691cSlogin pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
257bacd691cSlogin     // kdebug!("schedule_timeout");
258bacd691cSlogin     if timeout == MAX_TIMEOUT {
2598cb2e9b3SLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
260be8cdf4bSLoGin         ProcessManager::mark_sleep(true).ok();
2618cb2e9b3SLoGin         drop(irq_guard);
262*f0c87a89SGnoCiYeH         schedule(SchedMode::SM_PREEMPT);
263bacd691cSlogin         return Ok(MAX_TIMEOUT);
264bacd691cSlogin     } else if timeout < 0 {
265bacd691cSlogin         kerror!("timeout can't less than 0");
266bacd691cSlogin         return Err(SystemError::EINVAL);
267bacd691cSlogin     } else {
268bacd691cSlogin         // 禁用中断,防止在这段期间发生调度,造成死锁
26936fd0130Shoumkh         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
27036fd0130Shoumkh 
27136fd0130Shoumkh         timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
2721496ba7bSLoGin         let timer = Timer::new(
2731496ba7bSLoGin             WakeUpHelper::new(ProcessManager::current_pcb()),
2741496ba7bSLoGin             timeout as u64,
2751496ba7bSLoGin         );
2761496ba7bSLoGin         ProcessManager::mark_sleep(true).ok();
277bacd691cSlogin         timer.activate();
27836fd0130Shoumkh 
27936fd0130Shoumkh         drop(irq_guard);
280bacd691cSlogin 
281*f0c87a89SGnoCiYeH         schedule(SchedMode::SM_PREEMPT);
28236fd0130Shoumkh         let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
283bacd691cSlogin         if time_remaining >= 0 {
284bacd691cSlogin             // 被提前唤醒,返回剩余时间
285bacd691cSlogin             return Ok(time_remaining);
286bacd691cSlogin         } else {
287bacd691cSlogin             return Ok(0);
288bacd691cSlogin         }
289bacd691cSlogin     }
290bacd691cSlogin }
291bacd691cSlogin 
292bacd691cSlogin pub fn timer_get_first_expire() -> Result<u64, SystemError> {
293bacd691cSlogin     // FIXME
294bacd691cSlogin     // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
295bacd691cSlogin     for _ in 0..10 {
296be8cdf4bSLoGin         match TIMER_LIST.try_lock_irqsave() {
297bacd691cSlogin             Ok(timer_list) => {
298bacd691cSlogin                 // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
299bacd691cSlogin                 if timer_list.is_empty() {
300bacd691cSlogin                     // kdebug!("timer_list is empty");
301bacd691cSlogin                     return Ok(0);
302bacd691cSlogin                 } else {
303bacd691cSlogin                     // kdebug!("timer_list not empty");
304b8ed3825SDonkey Kane                     return Ok(timer_list.first().unwrap().0);
305bacd691cSlogin                 }
306bacd691cSlogin             }
307bacd691cSlogin             // 加锁失败返回啥??
308bacd691cSlogin             Err(_) => continue,
309bacd691cSlogin         }
310bacd691cSlogin     }
31179a452ceShoumkh     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
312bacd691cSlogin }
313bacd691cSlogin 
314be8cdf4bSLoGin /// 更新系统时间片
3150d6cf65aSLoGin pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
31636fd0130Shoumkh     let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
31736fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
3180d6cf65aSLoGin     update_wall_time(time_us);
31936fd0130Shoumkh 
32036fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
32136fd0130Shoumkh     return prev + add_jiffies;
322bacd691cSlogin }
32336fd0130Shoumkh 
324bacd691cSlogin pub fn clock() -> u64 {
32536fd0130Shoumkh     return TIMER_JIFFIES.load(Ordering::SeqCst);
326bacd691cSlogin }
327bacd691cSlogin 
328bacd691cSlogin // ====== 以下为给C提供的接口 ======
329bacd691cSlogin 
330bacd691cSlogin #[no_mangle]
331bacd691cSlogin pub extern "C" fn rs_timer_init() {
332bacd691cSlogin     timer_init();
333bacd691cSlogin }
334