arceos_posix_api/imp/
time.rs1use axerrno::LinuxError;
2use core::ffi::{c_int, c_long};
3use core::time::Duration;
4
5use crate::ctypes;
6use crate::ctypes::{CLOCK_MONOTONIC, CLOCK_REALTIME};
7
8impl From<ctypes::timespec> for Duration {
9 fn from(ts: ctypes::timespec) -> Self {
10 Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32)
11 }
12}
13
14impl From<ctypes::timeval> for Duration {
15 fn from(tv: ctypes::timeval) -> Self {
16 Duration::new(tv.tv_sec as u64, tv.tv_usec as u32 * 1000)
17 }
18}
19
20impl From<Duration> for ctypes::timespec {
21 fn from(d: Duration) -> Self {
22 ctypes::timespec {
23 tv_sec: d.as_secs() as c_long,
24 tv_nsec: d.subsec_nanos() as c_long,
25 }
26 }
27}
28
29impl From<Duration> for ctypes::timeval {
30 fn from(d: Duration) -> Self {
31 ctypes::timeval {
32 tv_sec: d.as_secs() as c_long,
33 tv_usec: d.subsec_micros() as c_long,
34 }
35 }
36}
37
38pub unsafe fn sys_clock_gettime(clk: ctypes::clockid_t, ts: *mut ctypes::timespec) -> c_int {
40 syscall_body!(sys_clock_gettime, {
41 if ts.is_null() {
42 return Err(LinuxError::EFAULT);
43 }
44 let now = match clk as u32 {
45 CLOCK_REALTIME => axhal::time::wall_time().into(),
46 CLOCK_MONOTONIC => axhal::time::monotonic_time().into(),
47 _ => {
48 warn!("Called sys_clock_gettime for unsupported clock {}", clk);
49 return Err(LinuxError::EINVAL);
50 }
51 };
52 unsafe { *ts = now };
53 debug!("sys_clock_gettime: {}.{:09}s", now.tv_sec, now.tv_nsec);
54 Ok(0)
55 })
56}
57
58pub unsafe fn sys_nanosleep(req: *const ctypes::timespec, rem: *mut ctypes::timespec) -> c_int {
62 syscall_body!(sys_nanosleep, {
63 unsafe {
64 if req.is_null() || (*req).tv_nsec < 0 || (*req).tv_nsec > 999999999 {
65 return Err(LinuxError::EINVAL);
66 }
67 }
68
69 let dur = unsafe {
70 debug!("sys_nanosleep <= {}.{:09}s", (*req).tv_sec, (*req).tv_nsec);
71 Duration::from(*req)
72 };
73
74 let now = axhal::time::monotonic_time();
75
76 #[cfg(feature = "multitask")]
77 axtask::sleep(dur);
78 #[cfg(not(feature = "multitask"))]
79 axhal::time::busy_wait(dur);
80
81 let after = axhal::time::monotonic_time();
82 let actual = after - now;
83
84 if let Some(diff) = dur.checked_sub(actual) {
85 if !rem.is_null() {
86 unsafe { (*rem) = diff.into() };
87 }
88 return Err(LinuxError::EINTR);
89 }
90 Ok(0)
91 })
92}