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