1use crate::arch;
2use crate::errno::*;
3use crate::syscalls::usleep;
4use crate::time::{itimerval, timespec, timeval};
5
6#[allow(non_camel_case_types)]
7pub type clockid_t = i32;
8
9pub(crate) const CLOCK_REALTIME: clockid_t = 1;
10pub(crate) const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
11pub(crate) const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3;
12pub(crate) const CLOCK_MONOTONIC: clockid_t = 4;
13pub(crate) const TIMER_ABSTIME: i32 = 4;
14
15#[hermit_macro::system]
26#[unsafe(no_mangle)]
27pub unsafe extern "C" fn sys_clock_getres(clock_id: clockid_t, res: *mut timespec) -> i32 {
28 assert!(
29 !res.is_null(),
30 "sys_clock_getres called with a zero res parameter"
31 );
32 let result = unsafe { &mut *res };
33
34 match clock_id {
35 CLOCK_REALTIME | CLOCK_PROCESS_CPUTIME_ID | CLOCK_THREAD_CPUTIME_ID | CLOCK_MONOTONIC => {
36 *result = timespec::from_usec(1);
38 0
39 }
40 _ => {
41 debug!("Called sys_clock_getres for unsupported clock {}", clock_id);
42 -EINVAL
43 }
44 }
45}
46
47#[hermit_macro::system]
56#[unsafe(no_mangle)]
57pub unsafe extern "C" fn sys_clock_gettime(clock_id: clockid_t, tp: *mut timespec) -> i32 {
58 assert!(
59 !tp.is_null(),
60 "sys_clock_gettime called with a zero tp parameter"
61 );
62 let result = unsafe { &mut *tp };
63
64 match clock_id {
65 CLOCK_REALTIME => {
66 *result = timespec::from_usec(arch::kernel::systemtime::now_micros() as i64);
67 0
68 }
69 CLOCK_MONOTONIC => {
70 *result = timespec::from_usec(arch::processor::get_timer_ticks() as i64);
71 0
72 }
73 _ => {
74 debug!(
75 "Called sys_clock_gettime for unsupported clock {}",
76 clock_id
77 );
78 -EINVAL
79 }
80 }
81}
82
83#[hermit_macro::system]
93#[unsafe(no_mangle)]
94pub unsafe extern "C" fn sys_clock_nanosleep(
95 clock_id: clockid_t,
96 flags: i32,
97 rqtp: *const timespec,
98 _rmtp: *mut timespec,
99) -> i32 {
100 assert!(
101 !rqtp.is_null(),
102 "sys_clock_nanosleep called with a zero rqtp parameter"
103 );
104 let requested_time = unsafe { &*rqtp };
105 if requested_time.tv_sec < 0 || requested_time.tv_nsec > 999_999_999 {
106 debug!("sys_clock_nanosleep called with an invalid requested time, returning -EINVAL");
107 return -EINVAL;
108 }
109
110 match clock_id {
111 CLOCK_REALTIME | CLOCK_MONOTONIC => {
112 let mut microseconds = (requested_time.tv_sec as u64) * 1_000_000
113 + (requested_time.tv_nsec as u64) / 1_000;
114
115 if flags & TIMER_ABSTIME > 0 {
116 if clock_id == CLOCK_REALTIME {
117 microseconds -= arch::kernel::systemtime::now_micros();
118 } else {
119 microseconds -= arch::processor::get_timer_ticks();
120 }
121 }
122
123 usleep(microseconds);
124 0
125 }
126 _ => -EINVAL,
127 }
128}
129
130#[hermit_macro::system]
131#[unsafe(no_mangle)]
132pub unsafe extern "C" fn sys_clock_settime(_clock_id: clockid_t, _tp: *const timespec) -> i32 {
133 debug!("sys_clock_settime is unimplemented, returning -EINVAL");
135 -EINVAL
136}
137
138#[hermit_macro::system]
145#[unsafe(no_mangle)]
146pub unsafe extern "C" fn sys_gettimeofday(tp: *mut timeval, tz: usize) -> i32 {
147 if let Some(result) = unsafe { tp.as_mut() } {
148 let microseconds = arch::kernel::systemtime::now_micros();
151 *result = timeval::from_usec(microseconds as i64);
152 }
153
154 if tz > 0 {
155 debug!("The tz parameter in sys_gettimeofday is unimplemented, returning -EINVAL");
156 return -EINVAL;
157 }
158
159 0
160}
161
162#[hermit_macro::system]
163#[unsafe(no_mangle)]
164pub unsafe extern "C" fn sys_setitimer(
165 _which: i32,
166 _value: *const itimerval,
167 _ovalue: *mut itimerval,
168) -> i32 {
169 debug!("Called sys_setitimer, which is unimplemented and always returns 0");
170 0
171}