1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /*
3 * time function definitions for NOLIBC
4 * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
5 */
6
7 /* make sure to include all global symbols */
8 #include "nolibc.h"
9
10 #ifndef _NOLIBC_TIME_H
11 #define _NOLIBC_TIME_H
12
13 #include "std.h"
14 #include "arch.h"
15 #include "types.h"
16 #include "sys.h"
17
18 #include <linux/signal.h>
19 #include <linux/time.h>
20
21 static __inline__
__nolibc_timespec_user_to_kernel(const struct timespec * ts,struct __kernel_timespec * kts)22 void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts)
23 {
24 kts->tv_sec = ts->tv_sec;
25 kts->tv_nsec = ts->tv_nsec;
26 }
27
28 static __inline__
__nolibc_timespec_kernel_to_user(const struct __kernel_timespec * kts,struct timespec * ts)29 void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struct timespec *ts)
30 {
31 ts->tv_sec = kts->tv_sec;
32 ts->tv_nsec = kts->tv_nsec;
33 }
34
35 /*
36 * int clock_getres(clockid_t clockid, struct timespec *res);
37 * int clock_gettime(clockid_t clockid, struct timespec *tp);
38 * int clock_settime(clockid_t clockid, const struct timespec *tp);
39 * int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
40 * struct timespec *rmtp)
41 */
42
43 static __attribute__((unused))
sys_clock_getres(clockid_t clockid,struct timespec * res)44 int sys_clock_getres(clockid_t clockid, struct timespec *res)
45 {
46 #if defined(__NR_clock_getres)
47 return my_syscall2(__NR_clock_getres, clockid, res);
48 #else
49 struct __kernel_timespec kres;
50 int ret;
51
52 ret = my_syscall2(__NR_clock_getres_time64, clockid, &kres);
53 if (res)
54 __nolibc_timespec_kernel_to_user(&kres, res);
55 return ret;
56 #endif
57 }
58
59 static __attribute__((unused))
clock_getres(clockid_t clockid,struct timespec * res)60 int clock_getres(clockid_t clockid, struct timespec *res)
61 {
62 return __sysret(sys_clock_getres(clockid, res));
63 }
64
65 static __attribute__((unused))
sys_clock_gettime(clockid_t clockid,struct timespec * tp)66 int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
67 {
68 #if defined(__NR_clock_gettime)
69 return my_syscall2(__NR_clock_gettime, clockid, tp);
70 #else
71 struct __kernel_timespec ktp;
72 int ret;
73
74 ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp);
75 if (tp)
76 __nolibc_timespec_kernel_to_user(&ktp, tp);
77 return ret;
78 #endif
79 }
80
81 static __attribute__((unused))
clock_gettime(clockid_t clockid,struct timespec * tp)82 int clock_gettime(clockid_t clockid, struct timespec *tp)
83 {
84 return __sysret(sys_clock_gettime(clockid, tp));
85 }
86
87 static __attribute__((unused))
sys_clock_settime(clockid_t clockid,struct timespec * tp)88 int sys_clock_settime(clockid_t clockid, struct timespec *tp)
89 {
90 #if defined(__NR_clock_settime)
91 return my_syscall2(__NR_clock_settime, clockid, tp);
92 #else
93 struct __kernel_timespec ktp;
94
95 __nolibc_timespec_user_to_kernel(tp, &ktp);
96 return my_syscall2(__NR_clock_settime64, clockid, &ktp);
97 #endif
98 }
99
100 static __attribute__((unused))
clock_settime(clockid_t clockid,struct timespec * tp)101 int clock_settime(clockid_t clockid, struct timespec *tp)
102 {
103 return __sysret(sys_clock_settime(clockid, tp));
104 }
105
106 static __attribute__((unused))
sys_clock_nanosleep(clockid_t clockid,int flags,const struct timespec * rqtp,struct timespec * rmtp)107 int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
108 struct timespec *rmtp)
109 {
110 #if defined(__NR_clock_nanosleep)
111 return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
112 #else
113 struct __kernel_timespec krqtp, krmtp;
114 int ret;
115
116 __nolibc_timespec_user_to_kernel(rqtp, &krqtp);
117 ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp);
118 if (rmtp)
119 __nolibc_timespec_kernel_to_user(&krmtp, rmtp);
120 return ret;
121 #endif
122 }
123
124 static __attribute__((unused))
clock_nanosleep(clockid_t clockid,int flags,const struct timespec * rqtp,struct timespec * rmtp)125 int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
126 struct timespec *rmtp)
127 {
128 /* Directly return a positive error number */
129 return -sys_clock_nanosleep(clockid, flags, rqtp, rmtp);
130 }
131
132 static __inline__
difftime(time_t time1,time_t time2)133 double difftime(time_t time1, time_t time2)
134 {
135 return time1 - time2;
136 }
137
138 static __inline__
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)139 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
140 {
141 return __sysret(sys_clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp));
142 }
143
144
145 static __attribute__((unused))
time(time_t * tptr)146 time_t time(time_t *tptr)
147 {
148 struct timeval tv;
149
150 /* note, cannot fail here */
151 sys_gettimeofday(&tv, NULL);
152
153 if (tptr)
154 *tptr = tv.tv_sec;
155 return tv.tv_sec;
156 }
157
158
159 /*
160 * int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
161 * int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
162 * int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
163 */
164
165 static __attribute__((unused))
sys_timer_create(clockid_t clockid,struct sigevent * evp,timer_t * timerid)166 int sys_timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
167 {
168 return my_syscall3(__NR_timer_create, clockid, evp, timerid);
169 }
170
171 static __attribute__((unused))
timer_create(clockid_t clockid,struct sigevent * evp,timer_t * timerid)172 int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
173 {
174 return __sysret(sys_timer_create(clockid, evp, timerid));
175 }
176
177 static __attribute__((unused))
sys_timer_delete(timer_t timerid)178 int sys_timer_delete(timer_t timerid)
179 {
180 return my_syscall1(__NR_timer_delete, timerid);
181 }
182
183 static __attribute__((unused))
timer_delete(timer_t timerid)184 int timer_delete(timer_t timerid)
185 {
186 return __sysret(sys_timer_delete(timerid));
187 }
188
189 static __attribute__((unused))
sys_timer_gettime(timer_t timerid,struct itimerspec * curr_value)190 int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
191 {
192 #if defined(__NR_timer_gettime)
193 return my_syscall2(__NR_timer_gettime, timerid, curr_value);
194 #else
195 struct __kernel_itimerspec kcurr_value;
196 int ret;
197
198 ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value);
199 __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
200 __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
201 return ret;
202 #endif
203 }
204
205 static __attribute__((unused))
timer_gettime(timer_t timerid,struct itimerspec * curr_value)206 int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
207 {
208 return __sysret(sys_timer_gettime(timerid, curr_value));
209 }
210
211 static __attribute__((unused))
sys_timer_settime(timer_t timerid,int flags,const struct itimerspec * new_value,struct itimerspec * old_value)212 int sys_timer_settime(timer_t timerid, int flags,
213 const struct itimerspec *new_value, struct itimerspec *old_value)
214 {
215 #if defined(__NR_timer_settime)
216 return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
217 #else
218 struct __kernel_itimerspec knew_value, kold_value;
219 int ret;
220
221 __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
222 __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
223 ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
224 if (old_value) {
225 __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
226 __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
227 }
228 return ret;
229 #endif
230 }
231
232 static __attribute__((unused))
timer_settime(timer_t timerid,int flags,const struct itimerspec * new_value,struct itimerspec * old_value)233 int timer_settime(timer_t timerid, int flags,
234 const struct itimerspec *new_value, struct itimerspec *old_value)
235 {
236 return __sysret(sys_timer_settime(timerid, flags, new_value, old_value));
237 }
238
239 #endif /* _NOLIBC_TIME_H */
240