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