xref: /DragonOS/kernel/src/process/timer.rs (revision f9fe30be89e89499aad4ef52b4648986bef5a7d8)
1 use crate::arch::ipc::signal::{SigCode, Signal};
2 use crate::exception::InterruptArch;
3 use crate::ipc::signal_types::SigType;
4 use crate::process::CurrentIrqArch;
5 use crate::process::Pid;
6 use crate::process::SigInfo;
7 use crate::time::timer::{clock, Jiffies, Timer, TimerFunction};
8 use alloc::{boxed::Box, sync::Arc};
9 use core::sync::atomic::compiler_fence;
10 use core::time::Duration;
11 use system_error::SystemError;
12 
13 /// 闹钟结构体
14 #[derive(Debug)]
15 pub struct AlarmTimer {
16     /// 闹钟内置定时器
17     pub timer: Arc<Timer>,
18     /// 闹钟触发时间
19     expired_second: u64,
20 }
21 
22 impl AlarmTimer {
23     /// # 创建闹钟结构体
24     ///
25     /// 自定义定时器触发函数和截止时间来创建闹钟结构体
26     ///
27     /// ## 函数参数
28     ///
29     /// timer_func:定时器触发函数
30     ///
31     /// second:设置alarm触发的秒数
32     ///
33     /// ### 函数返回值
34     ///
35     /// Self
36     pub fn new(timer_func: Box<dyn TimerFunction>, second: u64) -> Self {
37         let expired_jiffies =
38             <Jiffies as From<Duration>>::from(Duration::from_secs(second)).timer_jiffies();
39         let result = AlarmTimer {
40             timer: Timer::new(timer_func, expired_jiffies),
41             expired_second: second,
42         };
43         result
44     }
45     /// # 启动闹钟
46     pub fn activate(&self) {
47         let timer = self.timer.clone();
48         timer.activate();
49     }
50 
51     /// # 初始化目标进程的alarm定时器
52     ///
53     /// 创建一个闹钟结构体并启动闹钟
54     ///
55     /// ## 函数参数
56     ///
57     /// pid:发送消息的目标进程的pid
58     ///
59     /// second:设置alarm触发的秒数
60     ///
61     /// ### 函数返回值
62     ///
63     /// AlarmTimer结构体
64     pub fn alarm_timer_init(pid: Pid, second: u64) -> AlarmTimer {
65         //初始化Timerfunc
66         let timerfunc = AlarmTimerFunc::new(pid);
67         let alarmtimer = AlarmTimer::new(timerfunc, second);
68         alarmtimer.activate();
69         alarmtimer
70     }
71 
72     /// # 查看闹钟是否触发
73     pub fn timeout(&self) -> bool {
74         self.timer.timeout()
75     }
76 
77     /// # 返回闹钟定时器剩余时间
78     pub fn remain(&self) -> Duration {
79         if self.timer.timeout() {
80             Duration::ZERO
81         } else {
82             let now_jiffies = clock();
83             let end_jiffies =
84                 <Jiffies as From<Duration>>::from(Duration::from_secs(self.expired_second))
85                     .timer_jiffies();
86             let remain_second = Duration::from(Jiffies::new(end_jiffies - now_jiffies));
87             // debug!(
88             //     "end: {} - now: {} = remain: {}",
89             //     end_jiffies,
90             //     now_jiffies,
91             //     end_jiffies - now_jiffies
92             // );
93             remain_second
94         }
95     }
96     /// # 取消闹钟
97     pub fn cancel(&self) {
98         self.timer.cancel();
99     }
100 }
101 
102 /// # 闹钟TimerFuntion结构体
103 ///
104 /// ## 结构成员
105 ///
106 /// pid:发送消息的目标进程的pid
107 #[derive(Debug)]
108 pub struct AlarmTimerFunc {
109     pid: Pid,
110 }
111 
112 impl AlarmTimerFunc {
113     pub fn new(pid: Pid) -> Box<AlarmTimerFunc> {
114         return Box::new(AlarmTimerFunc { pid });
115     }
116 }
117 
118 impl TimerFunction for AlarmTimerFunc {
119     /// # 闹钟触发函数
120     ///
121     /// 闹钟触发时,向目标进程发送一个SIGALRM信号
122     ///
123     /// ## 函数参数
124     ///
125     /// expired_second:设置alarm触发的秒数
126     ///
127     /// ### 函数返回值
128     ///
129     /// Ok(()): 发送成功
130     fn run(&mut self) -> Result<(), SystemError> {
131         let sig = Signal::SIGALRM;
132         // 初始化signal info
133         let mut info = SigInfo::new(sig, 0, SigCode::Timer, SigType::Alarm(self.pid));
134 
135         compiler_fence(core::sync::atomic::Ordering::SeqCst);
136         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
137         let _retval = sig
138             .send_signal_info(Some(&mut info), self.pid)
139             .map(|x| x as usize)?;
140         compiler_fence(core::sync::atomic::Ordering::SeqCst);
141         drop(irq_guard);
142         Ok(())
143     }
144 }
145