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