xref: /linux/tools/include/nolibc/time.h (revision b22d81ed319cbe2d5b45f605cab18aaf82a66a50)
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__
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__
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))
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 #elif defined(__NR_clock_getres_time64)
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 #else
57 	return __nolibc_enosys(__func__, clockid, res);
58 #endif
59 }
60 
61 static __attribute__((unused))
62 int clock_getres(clockid_t clockid, struct timespec *res)
63 {
64 	return __sysret(sys_clock_getres(clockid, res));
65 }
66 
67 static __attribute__((unused))
68 int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
69 {
70 #if defined(__NR_clock_gettime)
71 	return my_syscall2(__NR_clock_gettime, clockid, tp);
72 #elif defined(__NR_clock_gettime64)
73 	struct __kernel_timespec ktp;
74 	int ret;
75 
76 	ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp);
77 	if (tp)
78 		__nolibc_timespec_kernel_to_user(&ktp, tp);
79 	return ret;
80 #else
81 	return __nolibc_enosys(__func__, clockid, tp);
82 #endif
83 }
84 
85 static __attribute__((unused))
86 int clock_gettime(clockid_t clockid, struct timespec *tp)
87 {
88 	return __sysret(sys_clock_gettime(clockid, tp));
89 }
90 
91 static __attribute__((unused))
92 int sys_clock_settime(clockid_t clockid, struct timespec *tp)
93 {
94 #if defined(__NR_clock_settime)
95 	return my_syscall2(__NR_clock_settime, clockid, tp);
96 #elif defined(__NR_clock_settime64)
97 	struct __kernel_timespec ktp;
98 
99 	__nolibc_timespec_user_to_kernel(tp, &ktp);
100 	return my_syscall2(__NR_clock_settime64, clockid, &ktp);
101 #else
102 	return __nolibc_enosys(__func__, clockid, tp);
103 #endif
104 }
105 
106 static __attribute__((unused))
107 int clock_settime(clockid_t clockid, struct timespec *tp)
108 {
109 	return __sysret(sys_clock_settime(clockid, tp));
110 }
111 
112 static __attribute__((unused))
113 int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
114 			struct timespec *rmtp)
115 {
116 #if defined(__NR_clock_nanosleep)
117 	return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
118 #elif defined(__NR_clock_nanosleep_time64)
119 	struct __kernel_timespec krqtp, krmtp;
120 	int ret;
121 
122 	__nolibc_timespec_user_to_kernel(rqtp, &krqtp);
123 	ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp);
124 	if (rmtp)
125 		__nolibc_timespec_kernel_to_user(&krmtp, rmtp);
126 	return ret;
127 #else
128 	return __nolibc_enosys(__func__, clockid, flags, rqtp, rmtp);
129 #endif
130 }
131 
132 static __attribute__((unused))
133 int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
134 		    struct timespec *rmtp)
135 {
136 	/* Directly return a positive error number */
137 	return -sys_clock_nanosleep(clockid, flags, rqtp, rmtp);
138 }
139 
140 static __inline__
141 double difftime(time_t time1, time_t time2)
142 {
143 	return time1 - time2;
144 }
145 
146 static __inline__
147 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
148 {
149 	return __sysret(sys_clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp));
150 }
151 
152 
153 static __attribute__((unused))
154 time_t time(time_t *tptr)
155 {
156 	struct timeval tv;
157 
158 	/* note, cannot fail here */
159 	sys_gettimeofday(&tv, NULL);
160 
161 	if (tptr)
162 		*tptr = tv.tv_sec;
163 	return tv.tv_sec;
164 }
165 
166 
167 /*
168  * int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
169  * int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
170  * int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
171  */
172 
173 static __attribute__((unused))
174 int sys_timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
175 {
176 	return my_syscall3(__NR_timer_create, clockid, evp, timerid);
177 }
178 
179 static __attribute__((unused))
180 int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
181 {
182 	return __sysret(sys_timer_create(clockid, evp, timerid));
183 }
184 
185 static __attribute__((unused))
186 int sys_timer_delete(timer_t timerid)
187 {
188 	return my_syscall1(__NR_timer_delete, timerid);
189 }
190 
191 static __attribute__((unused))
192 int timer_delete(timer_t timerid)
193 {
194 	return __sysret(sys_timer_delete(timerid));
195 }
196 
197 static __attribute__((unused))
198 int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
199 {
200 #if defined(__NR_timer_gettime)
201 	return my_syscall2(__NR_timer_gettime, timerid, curr_value);
202 #elif defined(__NR_timer_gettime64)
203 	struct __kernel_itimerspec kcurr_value;
204 	int ret;
205 
206 	ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value);
207 	__nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
208 	__nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
209 	return ret;
210 #else
211 	return __nolibc_enosys(__func__, timerid, curr_value);
212 #endif
213 }
214 
215 static __attribute__((unused))
216 int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
217 {
218 	return __sysret(sys_timer_gettime(timerid, curr_value));
219 }
220 
221 static __attribute__((unused))
222 int sys_timer_settime(timer_t timerid, int flags,
223 		      const struct itimerspec *new_value, struct itimerspec *old_value)
224 {
225 #if defined(__NR_timer_settime)
226 	return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
227 #elif defined(__NR_timer_settime64)
228 	struct __kernel_itimerspec knew_value, kold_value;
229 	int ret;
230 
231 	__nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
232 	__nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
233 	ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
234 	if (old_value) {
235 		__nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
236 		__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
237 	}
238 	return ret;
239 #else
240 	return __nolibc_enosys(__func__, timerid, flags, new_value, old_value);
241 #endif
242 }
243 
244 static __attribute__((unused))
245 int timer_settime(timer_t timerid, int flags,
246 		  const struct itimerspec *new_value, struct itimerspec *old_value)
247 {
248 	return __sysret(sys_timer_settime(timerid, flags, new_value, old_value));
249 }
250 
251 #endif /* _NOLIBC_TIME_H */
252