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