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