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!("Called sys_clock_gettime for unsupported clock {clock_id}");
75 -EINVAL
76 }
77 }
78}
79
80#[hermit_macro::system]
90#[unsafe(no_mangle)]
91pub unsafe extern "C" fn sys_clock_nanosleep(
92 clock_id: clockid_t,
93 flags: i32,
94 rqtp: *const timespec,
95 _rmtp: *mut timespec,
96) -> i32 {
97 assert!(
98 !rqtp.is_null(),
99 "sys_clock_nanosleep called with a zero rqtp parameter"
100 );
101 let requested_time = unsafe { &*rqtp };
102 if requested_time.tv_sec < 0 || requested_time.tv_nsec > 999_999_999 {
103 debug!("sys_clock_nanosleep called with an invalid requested time, returning -EINVAL");
104 return -EINVAL;
105 }
106
107 match clock_id {
108 CLOCK_REALTIME | CLOCK_MONOTONIC => {
109 let mut microseconds = (requested_time.tv_sec as u64) * 1_000_000
110 + (requested_time.tv_nsec as u64) / 1_000;
111
112 if flags & TIMER_ABSTIME > 0 {
113 if clock_id == CLOCK_REALTIME {
114 microseconds -= arch::kernel::systemtime::now_micros();
115 } else {
116 microseconds -= arch::processor::get_timer_ticks();
117 }
118 }
119
120 usleep(microseconds);
121 0
122 }
123 _ => -EINVAL,
124 }
125}
126
127#[hermit_macro::system]
128#[unsafe(no_mangle)]
129pub unsafe extern "C" fn sys_clock_settime(_clock_id: clockid_t, _tp: *const timespec) -> i32 {
130 debug!("sys_clock_settime is unimplemented, returning -EINVAL");
132 -EINVAL
133}
134
135#[hermit_macro::system]
142#[unsafe(no_mangle)]
143pub unsafe extern "C" fn sys_gettimeofday(tp: *mut timeval, tz: usize) -> i32 {
144 if let Some(result) = unsafe { tp.as_mut() } {
145 let microseconds = arch::kernel::systemtime::now_micros();
148 *result = timeval::from_usec(microseconds as i64);
149 }
150
151 if tz > 0 {
152 debug!("The tz parameter in sys_gettimeofday is unimplemented, returning -EINVAL");
153 return -EINVAL;
154 }
155
156 0
157}
158
159#[hermit_macro::system]
160#[unsafe(no_mangle)]
161pub unsafe extern "C" fn sys_setitimer(
162 _which: i32,
163 _value: *const itimerval,
164 _ovalue: *mut itimerval,
165) -> i32 {
166 debug!("Called sys_setitimer, which is unimplemented and always returns 0");
167 0
168}