xref: /DragonOS/kernel/src/time/syscall.rs (revision 5b59005f930266d0e9c0092373e894826150f862)
1 use core::{
2     ffi::{c_int, c_longlong},
3     ptr::null_mut,
4 };
5 
6 use num_traits::FromPrimitive;
7 use system_error::SystemError;
8 
9 use crate::{
10     syscall::{user_access::UserBufferWriter, Syscall},
11     time::{sleep::nanosleep, TimeSpec},
12 };
13 
14 use super::timekeeping::do_gettimeofday;
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 TimeSpec,
77         rm_time: *mut TimeSpec,
78     ) -> Result<usize, SystemError> {
79         if sleep_time == null_mut() {
80             return Err(SystemError::EFAULT);
81         }
82         let slt_spec = TimeSpec {
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 != null_mut() {
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 TimeSpec) -> Result<usize, SystemError> {
138         let clock_id = PosixClockID::try_from(clock_id)?;
139         if clock_id != PosixClockID::Realtime {
140             kwarn!("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 =
146             UserBufferWriter::new::<TimeSpec>(tp, core::mem::size_of::<TimeSpec>(), true)?;
147 
148         let posix_time = do_gettimeofday();
149 
150         tp_buf.copy_one_to_user(&posix_time, 0)?;
151 
152         return Ok(0);
153     }
154 }
155