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