xref: /DragonOS/kernel/src/time/syscall.rs (revision 83ed0ebc293d5a10245089f627f52770fd5b9dd4)
1 use core::{
2     ffi::{c_int, c_longlong},
3     ptr::null_mut,
4 };
5 
6 use num_traits::FromPrimitive;
7 
8 use crate::{
9     syscall::{user_access::UserBufferWriter, Syscall, SystemError},
10     time::{sleep::nanosleep, TimeSpec},
11 };
12 
13 use super::timekeeping::do_gettimeofday;
14 
15 pub type PosixTimeT = c_longlong;
16 pub type PosixSusecondsT = c_int;
17 
18 #[repr(C)]
19 #[derive(Default, Debug, Copy, Clone)]
20 pub struct PosixTimeval {
21     pub tv_sec: PosixTimeT,
22     pub tv_usec: PosixSusecondsT,
23 }
24 
25 #[repr(C)]
26 #[derive(Default, Debug, Copy, Clone)]
27 /// 当前时区信息
28 pub struct PosixTimeZone {
29     /// 格林尼治相对于当前时区相差的分钟数
30     pub tz_minuteswest: c_int,
31     /// DST矫正时差
32     pub tz_dsttime: c_int,
33 }
34 
35 /// 系统时区 暂时写定为东八区
36 pub const SYS_TIMEZONE: PosixTimeZone = PosixTimeZone {
37     tz_minuteswest: -480,
38     tz_dsttime: 0,
39 };
40 
41 /// The IDs of the various system clocks (for POSIX.1b interval timers):
42 #[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive)]
43 pub enum PosixClockID {
44     Realtime = 0,
45     Monotonic = 1,
46     ProcessCPUTimeID = 2,
47     ThreadCPUTimeID = 3,
48     MonotonicRaw = 4,
49     RealtimeCoarse = 5,
50     MonotonicCoarse = 6,
51     Boottime = 7,
52     RealtimeAlarm = 8,
53     BoottimeAlarm = 9,
54 }
55 
56 impl TryFrom<i32> for PosixClockID {
57     type Error = SystemError;
58 
59     fn try_from(value: i32) -> Result<Self, Self::Error> {
60         <Self as FromPrimitive>::from_i32(value).ok_or(SystemError::EINVAL)
61     }
62 }
63 
64 impl Syscall {
65     /// @brief 休眠指定时间(单位:纳秒)(提供给C的接口)
66     ///
67     /// @param sleep_time 指定休眠的时间
68     ///
69     /// @param rm_time 剩余休眠时间(传出参数)
70     ///
71     /// @return Ok(i32) 0
72     ///
73     /// @return Err(SystemError) 错误码
74     pub fn nanosleep(
75         sleep_time: *const TimeSpec,
76         rm_time: *mut TimeSpec,
77     ) -> Result<usize, SystemError> {
78         if sleep_time == null_mut() {
79             return Err(SystemError::EFAULT);
80         }
81         let slt_spec = TimeSpec {
82             tv_sec: unsafe { *sleep_time }.tv_sec,
83             tv_nsec: unsafe { *sleep_time }.tv_nsec,
84         };
85 
86         let r: Result<usize, SystemError> = nanosleep(slt_spec).map(|slt_spec| {
87             if rm_time != null_mut() {
88                 unsafe { *rm_time }.tv_sec = slt_spec.tv_sec;
89                 unsafe { *rm_time }.tv_nsec = slt_spec.tv_nsec;
90             }
91             0
92         });
93 
94         return r;
95     }
96 
97     /// 获取cpu时间
98     ///
99     /// todo: 该系统调用与Linux不一致,将来需要删除该系统调用!!! 删的时候记得改C版本的libc
100     pub fn clock() -> Result<usize, SystemError> {
101         return Ok(super::timer::clock() as usize);
102     }
103 
104     pub fn gettimeofday(
105         tv: *mut PosixTimeval,
106         timezone: *mut PosixTimeZone,
107     ) -> Result<usize, SystemError> {
108         // TODO; 处理时区信息
109         if tv.is_null() {
110             return Err(SystemError::EFAULT);
111         }
112         let mut tv_buf =
113             UserBufferWriter::new::<PosixTimeval>(tv, core::mem::size_of::<PosixTimeval>(), true)?;
114 
115         let tz_buf = if timezone.is_null() {
116             None
117         } else {
118             Some(UserBufferWriter::new::<PosixTimeZone>(
119                 timezone,
120                 core::mem::size_of::<PosixTimeZone>(),
121                 true,
122             )?)
123         };
124 
125         let posix_time = do_gettimeofday();
126 
127         tv_buf.copy_one_to_user(&posix_time, 0)?;
128 
129         if let Some(mut tz_buf) = tz_buf {
130             tz_buf.copy_one_to_user(&SYS_TIMEZONE, 0)?;
131         }
132 
133         return Ok(0);
134     }
135 
136     pub fn clock_gettime(clock_id: c_int, tp: *mut TimeSpec) -> Result<usize, SystemError> {
137         let clock_id = PosixClockID::try_from(clock_id)?;
138         if clock_id != PosixClockID::Realtime {
139             kwarn!("clock_gettime: currently only support Realtime clock, but got {:?}. Defaultly return realtime!!!\n", clock_id);
140         }
141         if tp.is_null() {
142             return Err(SystemError::EFAULT);
143         }
144         let mut tp_buf =
145             UserBufferWriter::new::<TimeSpec>(tp, core::mem::size_of::<TimeSpec>(), true)?;
146 
147         let posix_time = do_gettimeofday();
148 
149         tp_buf.copy_one_to_user(&posix_time, 0)?;
150 
151         return Ok(0);
152     }
153 }
154