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