xref: /DragonOS/kernel/src/time/timer.rs (revision af097f9f4b317337fe74aaa5070c34a14b8635fd)
136fd0130Shoumkh use core::{
236fd0130Shoumkh     fmt::Debug,
336fd0130Shoumkh     intrinsics::unlikely,
436fd0130Shoumkh     sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering},
5fbd63a30SSMALLC     time::Duration,
636fd0130Shoumkh };
7bacd691cSlogin 
8bacd691cSlogin use alloc::{
9bacd691cSlogin     boxed::Box,
10bacd691cSlogin     sync::{Arc, Weak},
11b8ed3825SDonkey Kane     vec::Vec,
12bacd691cSlogin };
132eab6dd7S曾俊 use log::{error, info, warn};
1491e9d4abSLoGin use system_error::SystemError;
15bacd691cSlogin 
16bacd691cSlogin use crate::{
17f0c87a89SGnoCiYeH     arch::CurrentIrqArch,
1836fd0130Shoumkh     exception::{
1936fd0130Shoumkh         softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
2036fd0130Shoumkh         InterruptArch,
21bacd691cSlogin     },
220d6cf65aSLoGin     libs::spinlock::{SpinLock, SpinLockGuard},
231496ba7bSLoGin     process::{ProcessControlBlock, ProcessManager},
24f0c87a89SGnoCiYeH     sched::{schedule, SchedMode},
25bacd691cSlogin };
26bacd691cSlogin 
27b8ed3825SDonkey Kane use super::{jiffies::NSEC_PER_JIFFY, timekeeping::update_wall_time};
2836fd0130Shoumkh 
29bacd691cSlogin const MAX_TIMEOUT: i64 = i64::MAX;
30bacd691cSlogin const TIMER_RUN_CYCLE_THRESHOLD: usize = 20;
3136fd0130Shoumkh static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0);
32bacd691cSlogin 
33bacd691cSlogin lazy_static! {
34b8ed3825SDonkey Kane     pub static ref TIMER_LIST: SpinLock<Vec<(u64, Arc<Timer>)>> = SpinLock::new(Vec::new());
35bacd691cSlogin }
36bacd691cSlogin 
37bacd691cSlogin /// 定时器要执行的函数的特征
3836fd0130Shoumkh pub trait TimerFunction: Send + Sync + Debug {
run(&mut self) -> Result<(), SystemError>3936fd0130Shoumkh     fn run(&mut self) -> Result<(), SystemError>;
40bacd691cSlogin }
41fbd63a30SSMALLC // # Jiffies结构体(注意这是一段时间的jiffies数而不是某一时刻的定时器时间片)
42fbd63a30SSMALLC 
43fbd63a30SSMALLC int_like!(Jiffies, u64);
44fbd63a30SSMALLC 
45fbd63a30SSMALLC impl Jiffies {
46fbd63a30SSMALLC     /// ## 返回接下来的n_jiffies对应的定时器时间片
timer_jiffies(&self) -> u6447fbd63a30SSMALLC     pub fn timer_jiffies(&self) -> u64 {
48fbd63a30SSMALLC         let result = TIMER_JIFFIES.load(Ordering::SeqCst) + self.data();
49fbd63a30SSMALLC         result
50fbd63a30SSMALLC     }
51fbd63a30SSMALLC }
52fbd63a30SSMALLC 
53fbd63a30SSMALLC impl From<Jiffies> for Duration {
54fbd63a30SSMALLC     /// # Jiffies转Duration
55fbd63a30SSMALLC     ///
56fbd63a30SSMALLC     /// ## 参数
57fbd63a30SSMALLC     ///
58fbd63a30SSMALLC     /// jiffies: 一段时间的jiffies数
59fbd63a30SSMALLC     ///
60fbd63a30SSMALLC     /// ### 返回值
61fbd63a30SSMALLC     ///
62fbd63a30SSMALLC     /// Duration: 这段时间的Duration形式
from(jiffies: Jiffies) -> Self63fbd63a30SSMALLC     fn from(jiffies: Jiffies) -> Self {
64fbd63a30SSMALLC         let ms = jiffies.data() / 1_000_000 * NSEC_PER_JIFFY as u64;
65fbd63a30SSMALLC         let result = Duration::from_millis(ms);
66fbd63a30SSMALLC         result
67fbd63a30SSMALLC     }
68fbd63a30SSMALLC }
69fbd63a30SSMALLC 
70fbd63a30SSMALLC impl From<Duration> for Jiffies {
71fbd63a30SSMALLC     /// # Duration 转 Jiffies
72fbd63a30SSMALLC     ///
73fbd63a30SSMALLC     /// ## 参数
74fbd63a30SSMALLC     ///
75fbd63a30SSMALLC     /// ms: 表示一段时间的Duration类型
76fbd63a30SSMALLC     ///
77fbd63a30SSMALLC     /// ### 返回值
78fbd63a30SSMALLC     ///
79fbd63a30SSMALLC     /// Jiffies结构体: 这段时间的Jiffies数
from(ms: Duration) -> Self80fbd63a30SSMALLC     fn from(ms: Duration) -> Self {
81fbd63a30SSMALLC         let jiffies = ms.as_millis() as u64 * 1_000_000 / NSEC_PER_JIFFY as u64;
82fbd63a30SSMALLC         let result = Jiffies::new(jiffies);
83fbd63a30SSMALLC         result
84fbd63a30SSMALLC     }
85fbd63a30SSMALLC }
86bacd691cSlogin 
8736fd0130Shoumkh #[derive(Debug)]
88bacd691cSlogin /// WakeUpHelper函数对应的结构体
89bacd691cSlogin pub struct WakeUpHelper {
901496ba7bSLoGin     pcb: Arc<ProcessControlBlock>,
91bacd691cSlogin }
92bacd691cSlogin 
93bacd691cSlogin impl WakeUpHelper {
new(pcb: Arc<ProcessControlBlock>) -> Box<WakeUpHelper>941496ba7bSLoGin     pub fn new(pcb: Arc<ProcessControlBlock>) -> Box<WakeUpHelper> {
95bacd691cSlogin         return Box::new(WakeUpHelper { pcb });
96bacd691cSlogin     }
97bacd691cSlogin }
98bacd691cSlogin 
99bacd691cSlogin impl TimerFunction for WakeUpHelper {
run(&mut self) -> Result<(), SystemError>10036fd0130Shoumkh     fn run(&mut self) -> Result<(), SystemError> {
1011496ba7bSLoGin         ProcessManager::wakeup(&self.pcb).ok();
10236fd0130Shoumkh         return Ok(());
103bacd691cSlogin     }
104bacd691cSlogin }
105bacd691cSlogin 
10636fd0130Shoumkh #[derive(Debug)]
1070d6cf65aSLoGin pub struct Timer {
1080d6cf65aSLoGin     inner: SpinLock<InnerTimer>,
1090d6cf65aSLoGin }
110bacd691cSlogin 
111bacd691cSlogin impl Timer {
112bacd691cSlogin     /// @brief 创建一个定时器(单位:ms)
113bacd691cSlogin     ///
114bacd691cSlogin     /// @param timer_func 定时器需要执行的函数对应的结构体
115bacd691cSlogin     ///
116bacd691cSlogin     /// @param expire_jiffies 定时器结束时刻
117bacd691cSlogin     ///
118bacd691cSlogin     /// @return 定时器结构体
new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self>119bacd691cSlogin     pub fn new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self> {
1200d6cf65aSLoGin         let result: Arc<Timer> = Arc::new(Timer {
1210d6cf65aSLoGin             inner: SpinLock::new(InnerTimer {
122bacd691cSlogin                 expire_jiffies,
1230d6cf65aSLoGin                 timer_func: Some(timer_func),
124bacd691cSlogin                 self_ref: Weak::default(),
125971462beSGnoCiYeH                 triggered: false,
1260d6cf65aSLoGin             }),
1270d6cf65aSLoGin         });
128bacd691cSlogin 
1290d6cf65aSLoGin         result.inner.lock().self_ref = Arc::downgrade(&result);
130bacd691cSlogin 
131bacd691cSlogin         return result;
132bacd691cSlogin     }
133bacd691cSlogin 
inner(&self) -> SpinLockGuard<InnerTimer>1340d6cf65aSLoGin     pub fn inner(&self) -> SpinLockGuard<InnerTimer> {
1350d6cf65aSLoGin         return self.inner.lock_irqsave();
1360d6cf65aSLoGin     }
1370d6cf65aSLoGin 
138bacd691cSlogin     /// @brief 将定时器插入到定时器链表中
activate(&self)139bacd691cSlogin     pub fn activate(&self) {
1400d6cf65aSLoGin         let mut timer_list = TIMER_LIST.lock_irqsave();
1410d6cf65aSLoGin         let inner_guard = self.inner();
142cde5492fSlogin 
143bacd691cSlogin         // 链表为空,则直接插入
144bacd691cSlogin         if timer_list.is_empty() {
145bacd691cSlogin             // FIXME push_timer
146b8ed3825SDonkey Kane             timer_list.push((
147b8ed3825SDonkey Kane                 inner_guard.expire_jiffies,
148b8ed3825SDonkey Kane                 inner_guard.self_ref.upgrade().unwrap(),
149b8ed3825SDonkey Kane             ));
150cde5492fSlogin 
151cde5492fSlogin             drop(inner_guard);
152cde5492fSlogin             drop(timer_list);
153cde5492fSlogin             compiler_fence(Ordering::SeqCst);
154cde5492fSlogin 
155bacd691cSlogin             return;
156bacd691cSlogin         }
157b8ed3825SDonkey Kane         let expire_jiffies = inner_guard.expire_jiffies;
158b8ed3825SDonkey Kane         let self_arc = inner_guard.self_ref.upgrade().unwrap();
159b8ed3825SDonkey Kane         drop(inner_guard);
160bacd691cSlogin         let mut split_pos: usize = 0;
161bacd691cSlogin         for (pos, elt) in timer_list.iter().enumerate() {
162b8ed3825SDonkey Kane             if Arc::ptr_eq(&self_arc, &elt.1) {
1632eab6dd7S曾俊                 warn!("Timer already in list");
164b8ed3825SDonkey Kane             }
165b8ed3825SDonkey Kane             if elt.0 > expire_jiffies {
166bacd691cSlogin                 split_pos = pos;
167bacd691cSlogin                 break;
168bacd691cSlogin             }
169bacd691cSlogin         }
170b8ed3825SDonkey Kane         timer_list.insert(split_pos, (expire_jiffies, self_arc));
171b8ed3825SDonkey Kane 
172cde5492fSlogin         drop(timer_list);
173bacd691cSlogin     }
174bacd691cSlogin 
175bacd691cSlogin     #[inline]
run(&self)176bacd691cSlogin     fn run(&self) {
1770d6cf65aSLoGin         let mut timer = self.inner();
178971462beSGnoCiYeH         timer.triggered = true;
1790d6cf65aSLoGin         let func = timer.timer_func.take();
1800d6cf65aSLoGin         drop(timer);
1810d6cf65aSLoGin         let r = func.map(|mut f| f.run()).unwrap_or(Ok(()));
18236fd0130Shoumkh         if unlikely(r.is_err()) {
1832eab6dd7S曾俊             error!(
18436fd0130Shoumkh                 "Failed to run timer function: {self:?} {:?}",
1858d72b68dSJomo                 r.as_ref().err().unwrap()
18636fd0130Shoumkh             );
18736fd0130Shoumkh         }
188bacd691cSlogin     }
189971462beSGnoCiYeH 
190971462beSGnoCiYeH     /// ## 判断定时器是否已经触发
timeout(&self) -> bool191971462beSGnoCiYeH     pub fn timeout(&self) -> bool {
1920d6cf65aSLoGin         self.inner().triggered
193971462beSGnoCiYeH     }
194971462beSGnoCiYeH 
195971462beSGnoCiYeH     /// ## 取消定时器任务
cancel(&self) -> bool196971462beSGnoCiYeH     pub fn cancel(&self) -> bool {
1970d6cf65aSLoGin         let this_arc = self.inner().self_ref.upgrade().unwrap();
198971462beSGnoCiYeH         TIMER_LIST
1990d6cf65aSLoGin             .lock_irqsave()
200b8ed3825SDonkey Kane             .extract_if(|x| Arc::ptr_eq(&this_arc, &x.1))
201840045afSLoGin             .for_each(drop);
202971462beSGnoCiYeH         true
203971462beSGnoCiYeH     }
204bacd691cSlogin }
205bacd691cSlogin 
206bacd691cSlogin /// 定时器类型
20736fd0130Shoumkh #[derive(Debug)]
208bacd691cSlogin pub struct InnerTimer {
209bacd691cSlogin     /// 定时器结束时刻
210bacd691cSlogin     pub expire_jiffies: u64,
211bacd691cSlogin     /// 定时器需要执行的函数结构体
2120d6cf65aSLoGin     pub timer_func: Option<Box<dyn TimerFunction>>,
213bacd691cSlogin     /// self_ref
214bacd691cSlogin     self_ref: Weak<Timer>,
215971462beSGnoCiYeH     /// 判断该计时器是否触发
216971462beSGnoCiYeH     triggered: bool,
217bacd691cSlogin }
218bacd691cSlogin 
219bacd691cSlogin #[derive(Debug)]
220bacd691cSlogin pub struct DoTimerSoftirq {
221bacd691cSlogin     running: AtomicBool,
222bacd691cSlogin }
223bacd691cSlogin 
224bacd691cSlogin impl DoTimerSoftirq {
new() -> Self225bacd691cSlogin     pub fn new() -> Self {
226bacd691cSlogin         return DoTimerSoftirq {
227bacd691cSlogin             running: AtomicBool::new(false),
228bacd691cSlogin         };
229bacd691cSlogin     }
230bacd691cSlogin 
set_run(&self) -> bool231bacd691cSlogin     fn set_run(&self) -> bool {
232bacd691cSlogin         let x = self
233bacd691cSlogin             .running
234bacd691cSlogin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed);
235840045afSLoGin         return x.is_ok();
236bacd691cSlogin     }
237bacd691cSlogin 
clear_run(&self)238bacd691cSlogin     fn clear_run(&self) {
239bacd691cSlogin         self.running.store(false, Ordering::Release);
240bacd691cSlogin     }
241bacd691cSlogin }
242bacd691cSlogin impl SoftirqVec for DoTimerSoftirq {
run(&self)243bacd691cSlogin     fn run(&self) {
244840045afSLoGin         if !self.set_run() {
245bacd691cSlogin             return;
246bacd691cSlogin         }
247bacd691cSlogin         // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器
248bacd691cSlogin         for _ in 0..TIMER_RUN_CYCLE_THRESHOLD {
2492eab6dd7S曾俊             // debug!("DoTimerSoftirq run");
2500d6cf65aSLoGin             let timer_list = TIMER_LIST.try_lock_irqsave();
251cde5492fSlogin             if timer_list.is_err() {
252cde5492fSlogin                 continue;
253cde5492fSlogin             }
254cde5492fSlogin             let mut timer_list = timer_list.unwrap();
255bacd691cSlogin 
256bacd691cSlogin             if timer_list.is_empty() {
257bacd691cSlogin                 break;
258bacd691cSlogin             }
259bacd691cSlogin 
260b8ed3825SDonkey Kane             let (front_jiffies, timer_list_front) = timer_list.first().unwrap().clone();
2612eab6dd7S曾俊             // debug!("to lock timer_list_front");
262b8ed3825SDonkey Kane 
263b8ed3825SDonkey Kane             if front_jiffies >= TIMER_JIFFIES.load(Ordering::SeqCst) {
264cde5492fSlogin                 break;
265cde5492fSlogin             }
266b8ed3825SDonkey Kane             timer_list.remove(0);
267cde5492fSlogin             drop(timer_list);
268cde5492fSlogin             timer_list_front.run();
269bacd691cSlogin         }
270bacd691cSlogin 
271bacd691cSlogin         self.clear_run();
272bacd691cSlogin     }
273bacd691cSlogin }
274bacd691cSlogin 
2755b59005fSLoGin /// 初始化系统定时器
2765b59005fSLoGin #[inline(never)]
timer_init()277bacd691cSlogin pub fn timer_init() {
278bacd691cSlogin     // FIXME 调用register_trap
279bacd691cSlogin     let do_timer_softirq = Arc::new(DoTimerSoftirq::new());
280bacd691cSlogin     softirq_vectors()
281bacd691cSlogin         .register_softirq(SoftirqNumber::TIMER, do_timer_softirq)
282bacd691cSlogin         .expect("Failed to register timer softirq");
2832eab6dd7S曾俊     info!("timer initialized successfully");
284bacd691cSlogin }
285bacd691cSlogin 
286bacd691cSlogin /// 计算接下来n毫秒对应的定时器时间片
next_n_ms_timer_jiffies(expire_ms: u64) -> u64287bacd691cSlogin pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 {
288b8ed3825SDonkey Kane     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_ms * 1000000 / NSEC_PER_JIFFY as u64;
289bacd691cSlogin }
290bacd691cSlogin /// 计算接下来n微秒对应的定时器时间片
next_n_us_timer_jiffies(expire_us: u64) -> u64291bacd691cSlogin pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 {
292b8ed3825SDonkey Kane     return TIMER_JIFFIES.load(Ordering::SeqCst) + expire_us * 1000 / NSEC_PER_JIFFY as u64;
293bacd691cSlogin }
294bacd691cSlogin 
295bacd691cSlogin /// @brief 让pcb休眠timeout个jiffies
296bacd691cSlogin ///
297bacd691cSlogin /// @param timeout 需要休眠的时间(单位:jiffies)
298bacd691cSlogin ///
299bacd691cSlogin /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies)
300bacd691cSlogin ///
301bacd691cSlogin /// @return Err(SystemError) 错误码
schedule_timeout(mut timeout: i64) -> Result<i64, SystemError>302bacd691cSlogin pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
3032eab6dd7S曾俊     // debug!("schedule_timeout");
304bacd691cSlogin     if timeout == MAX_TIMEOUT {
3058cb2e9b3SLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
306be8cdf4bSLoGin         ProcessManager::mark_sleep(true).ok();
3078cb2e9b3SLoGin         drop(irq_guard);
3083959e94dS曾俊         schedule(SchedMode::SM_NONE);
309bacd691cSlogin         return Ok(MAX_TIMEOUT);
310bacd691cSlogin     } else if timeout < 0 {
3112eab6dd7S曾俊         error!("timeout can't less than 0");
312bacd691cSlogin         return Err(SystemError::EINVAL);
313bacd691cSlogin     } else {
314bacd691cSlogin         // 禁用中断,防止在这段期间发生调度,造成死锁
31536fd0130Shoumkh         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
31636fd0130Shoumkh 
31736fd0130Shoumkh         timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
3181496ba7bSLoGin         let timer = Timer::new(
3191496ba7bSLoGin             WakeUpHelper::new(ProcessManager::current_pcb()),
3201496ba7bSLoGin             timeout as u64,
3211496ba7bSLoGin         );
3221496ba7bSLoGin         ProcessManager::mark_sleep(true).ok();
323bacd691cSlogin         timer.activate();
32436fd0130Shoumkh 
32536fd0130Shoumkh         drop(irq_guard);
326bacd691cSlogin 
3273959e94dS曾俊         schedule(SchedMode::SM_NONE);
32836fd0130Shoumkh         let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
329bacd691cSlogin         if time_remaining >= 0 {
330bacd691cSlogin             // 被提前唤醒,返回剩余时间
331bacd691cSlogin             return Ok(time_remaining);
332bacd691cSlogin         } else {
333bacd691cSlogin             return Ok(0);
334bacd691cSlogin         }
335bacd691cSlogin     }
336bacd691cSlogin }
337bacd691cSlogin 
timer_get_first_expire() -> Result<u64, SystemError>338bacd691cSlogin pub fn timer_get_first_expire() -> Result<u64, SystemError> {
339bacd691cSlogin     // FIXME
3402eab6dd7S曾俊     // debug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
341bacd691cSlogin     for _ in 0..10 {
342be8cdf4bSLoGin         match TIMER_LIST.try_lock_irqsave() {
343bacd691cSlogin             Ok(timer_list) => {
3442eab6dd7S曾俊                 // debug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
345bacd691cSlogin                 if timer_list.is_empty() {
3462eab6dd7S曾俊                     // debug!("timer_list is empty");
347bacd691cSlogin                     return Ok(0);
348bacd691cSlogin                 } else {
3492eab6dd7S曾俊                     // debug!("timer_list not empty");
350b8ed3825SDonkey Kane                     return Ok(timer_list.first().unwrap().0);
351bacd691cSlogin                 }
352bacd691cSlogin             }
353bacd691cSlogin             // 加锁失败返回啥??
354bacd691cSlogin             Err(_) => continue,
355bacd691cSlogin         }
356bacd691cSlogin     }
35779a452ceShoumkh     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
358bacd691cSlogin }
359bacd691cSlogin 
3600722a06aSLoGin /// 检查是否需要触发定时器软中断,如果需要则触发
try_raise_timer_softirq()3610722a06aSLoGin pub fn try_raise_timer_softirq() {
3620722a06aSLoGin     if let Ok(first_expire) = timer_get_first_expire() {
3630722a06aSLoGin         if first_expire <= clock() {
3640722a06aSLoGin             softirq_vectors().raise_softirq(SoftirqNumber::TIMER);
3650722a06aSLoGin         }
3660722a06aSLoGin     }
3670722a06aSLoGin }
3680722a06aSLoGin 
369*af097f9fS黄铭涛 /// 处理本地定时器中断
run_local_timer()370*af097f9fS黄铭涛 pub fn run_local_timer() {
371*af097f9fS黄铭涛     assert!(!CurrentIrqArch::is_irq_enabled());
372*af097f9fS黄铭涛     try_raise_timer_softirq();
373*af097f9fS黄铭涛 }
374*af097f9fS黄铭涛 
375be8cdf4bSLoGin /// 更新系统时间片
update_timer_jiffies(add_jiffies: u64) -> u64376*af097f9fS黄铭涛 pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
37736fd0130Shoumkh     let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
37836fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
379*af097f9fS黄铭涛     update_wall_time();
38036fd0130Shoumkh 
38136fd0130Shoumkh     compiler_fence(Ordering::SeqCst);
38236fd0130Shoumkh     return prev + add_jiffies;
383bacd691cSlogin }
38436fd0130Shoumkh 
clock() -> u64385bacd691cSlogin pub fn clock() -> u64 {
38636fd0130Shoumkh     return TIMER_JIFFIES.load(Ordering::SeqCst);
387bacd691cSlogin }
388bacd691cSlogin 
389bacd691cSlogin // ====== 以下为给C提供的接口 ======
390bacd691cSlogin 
391bacd691cSlogin #[no_mangle]
rs_timer_init()392bacd691cSlogin pub extern "C" fn rs_timer_init() {
393bacd691cSlogin     timer_init();
394bacd691cSlogin }
395