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