xref: /DragonOS/kernel/src/time/syscall.rs (revision 28fe4ad2a0b0d8b5abf1f0cb402b1c3204b42242) !
1 use core::{
2     ffi::{c_int, c_longlong},
3     time::Duration,
4 };
5 
6 use log::warn;
7 use num_traits::FromPrimitive;
8 use system_error::SystemError;
9 
10 use crate::{
11     process::{timer::AlarmTimer, ProcessManager},
12     syscall::{user_access::UserBufferWriter, Syscall},
13     time::{sleep::nanosleep, PosixTimeSpec},
14 };
15 
16 use super::timekeeping::{do_gettimeofday, getnstimeofday};
17 
18 pub type PosixTimeT = c_longlong;
19 pub type PosixSusecondsT = c_int;
20 
21 #[repr(C)]
22 #[derive(Default, Debug, Copy, Clone)]
23 pub struct PosixTimeval {
24     pub tv_sec: PosixTimeT,
25     pub tv_usec: PosixSusecondsT,
26 }
27 
28 #[repr(C)]
29 #[derive(Default, Debug, Copy, Clone)]
30 /// 当前时区信息
31 pub struct PosixTimeZone {
32     /// 格林尼治相对于当前时区相差的分钟数
33     pub tz_minuteswest: c_int,
34     /// DST矫正时差
35     pub tz_dsttime: c_int,
36 }
37 
38 /// 系统时区 暂时写定为东八区
39 pub const SYS_TIMEZONE: PosixTimeZone = PosixTimeZone {
40     tz_minuteswest: -480,
41     tz_dsttime: 0,
42 };
43 
44 /// The IDs of the various system clocks (for POSIX.1b interval timers):
45 #[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive)]
46 pub enum PosixClockID {
47     Realtime = 0,
48     Monotonic = 1,
49     ProcessCPUTimeID = 2,
50     ThreadCPUTimeID = 3,
51     MonotonicRaw = 4,
52     RealtimeCoarse = 5,
53     MonotonicCoarse = 6,
54     Boottime = 7,
55     RealtimeAlarm = 8,
56     BoottimeAlarm = 9,
57 }
58 
59 impl TryFrom<i32> for PosixClockID {
60     type Error = SystemError;
61 
62     fn try_from(value: i32) -> Result<Self, Self::Error> {
63         <Self as FromPrimitive>::from_i32(value).ok_or(SystemError::EINVAL)
64     }
65 }
66 
67 impl Syscall {
68     /// @brief 休眠指定时间(单位:纳秒)(提供给C的接口)
69     ///
70     /// @param sleep_time 指定休眠的时间
71     ///
72     /// @param rm_time 剩余休眠时间(传出参数)
73     ///
74     /// @return Ok(i32) 0
75     ///
76     /// @return Err(SystemError) 错误码
77     pub fn nanosleep(
78         sleep_time: *const PosixTimeSpec,
79         rm_time: *mut PosixTimeSpec,
80     ) -> Result<usize, SystemError> {
81         if sleep_time.is_null() {
82             return Err(SystemError::EFAULT);
83         }
84         let slt_spec = PosixTimeSpec {
85             tv_sec: unsafe { *sleep_time }.tv_sec,
86             tv_nsec: unsafe { *sleep_time }.tv_nsec,
87         };
88 
89         let r: Result<usize, SystemError> = nanosleep(slt_spec).map(|slt_spec| {
90             if !rm_time.is_null() {
91                 unsafe { *rm_time }.tv_sec = slt_spec.tv_sec;
92                 unsafe { *rm_time }.tv_nsec = slt_spec.tv_nsec;
93             }
94             0
95         });
96 
97         return r;
98     }
99 
100     /// 获取cpu时间
101     ///
102     /// todo: 该系统调用与Linux不一致,将来需要删除该系统调用!!! 删的时候记得改C版本的libc
103     pub fn clock() -> Result<usize, SystemError> {
104         return Ok(super::timer::clock() as usize);
105     }
106 
107     pub fn gettimeofday(
108         tv: *mut PosixTimeval,
109         timezone: *mut PosixTimeZone,
110     ) -> Result<usize, SystemError> {
111         // TODO; 处理时区信息
112         if tv.is_null() {
113             return Err(SystemError::EFAULT);
114         }
115         let mut tv_buf =
116             UserBufferWriter::new::<PosixTimeval>(tv, core::mem::size_of::<PosixTimeval>(), true)?;
117 
118         let tz_buf = if timezone.is_null() {
119             None
120         } else {
121             Some(UserBufferWriter::new::<PosixTimeZone>(
122                 timezone,
123                 core::mem::size_of::<PosixTimeZone>(),
124                 true,
125             )?)
126         };
127 
128         let posix_time = do_gettimeofday();
129 
130         tv_buf.copy_one_to_user(&posix_time, 0)?;
131 
132         if let Some(mut tz_buf) = tz_buf {
133             tz_buf.copy_one_to_user(&SYS_TIMEZONE, 0)?;
134         }
135 
136         return Ok(0);
137     }
138 
139     pub fn clock_gettime(clock_id: c_int, tp: *mut PosixTimeSpec) -> Result<usize, SystemError> {
140         let clock_id = PosixClockID::try_from(clock_id)?;
141         if clock_id != PosixClockID::Realtime {
142             warn!("clock_gettime: currently only support Realtime clock, but got {:?}. Defaultly return realtime!!!\n", clock_id);
143         }
144         if tp.is_null() {
145             return Err(SystemError::EFAULT);
146         }
147         let mut tp_buf = UserBufferWriter::new::<PosixTimeSpec>(
148             tp,
149             core::mem::size_of::<PosixTimeSpec>(),
150             true,
151         )?;
152 
153         let timespec = getnstimeofday();
154 
155         tp_buf.copy_one_to_user(&timespec, 0)?;
156 
157         return Ok(0);
158     }
159     /// # alarm函数功能
160     ///
161     /// 设置alarm(单位:秒)
162     ///
163     /// ## 函数参数
164     ///
165     /// expired_second:设置alarm触发的秒数
166     ///
167     /// ### 函数返回值
168     ///
169     /// Ok(usize): 上一个alarm的剩余秒数
170     pub fn alarm(expired_second: u32) -> Result<usize, SystemError> {
171         //初始化second
172         let second = Duration::from_secs(expired_second as u64);
173         let pcb = ProcessManager::current_pcb();
174         let mut pcb_alarm = pcb.alarm_timer_irqsave();
175         let alarm = pcb_alarm.as_ref();
176         //alarm第一次调用
177         if alarm.is_none() {
178             //注册alarm定时器
179             let pid = ProcessManager::current_pid();
180             let new_alarm = Some(AlarmTimer::alarm_timer_init(pid, 0));
181             *pcb_alarm = new_alarm;
182             drop(pcb_alarm);
183             return Ok(0);
184         }
185         //查询上一个alarm的剩余时间和重新注册alarm
186         let alarmtimer = alarm.unwrap();
187         let remain = alarmtimer.remain();
188         if second.is_zero() {
189             alarmtimer.cancel();
190         }
191         if !alarmtimer.timeout() {
192             alarmtimer.cancel();
193         }
194         let pid = ProcessManager::current_pid();
195         let new_alarm = Some(AlarmTimer::alarm_timer_init(pid, second.as_secs()));
196         *pcb_alarm = new_alarm;
197         drop(pcb_alarm);
198         return Ok(remain.as_secs() as usize);
199     }
200 }
201