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, PosixTimeSpec}, 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 PosixTimeSpec, 74 rm_time: *mut PosixTimeSpec, 75 ) -> Result<usize, SystemError> { 76 if sleep_time.is_null() { 77 return Err(SystemError::EFAULT); 78 } 79 let slt_spec = PosixTimeSpec { 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 PosixTimeSpec) -> 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 = UserBufferWriter::new::<PosixTimeSpec>( 143 tp, 144 core::mem::size_of::<PosixTimeSpec>(), 145 true, 146 )?; 147 148 let timespec = getnstimeofday(); 149 150 tp_buf.copy_one_to_user(×pec, 0)?; 151 152 return Ok(0); 153 } 154 } 155