@@ -1424,6 +1424,7 @@
* nptl/thrd_sleep.c: Use clock_nanosleep_time64 instead of nanosleep.
* sysdeps/unix/sysv/linux/nanosleep.c: Likewise.
* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: Likewise.
+ * sysdeps/unix/sysv/linux/gettimeofday.c: Use clock_gettime64 syscall for gettimeofday.
2019-06-20 Dmitry V. Levin <ldv@altlinux.org>
Florian Weimer <fweimer@redhat.com>
@@ -32,7 +32,58 @@
int
__gettimeofday (struct timeval *tv, struct timezone *tz)
{
+#ifdef __ASSUME_TIME64_SYSCALLS
+ long int ret;
+ struct timespec now;
+
+ ret = INLINE_VSYSCALL (clock_gettime64, 2, CLOCK_REALTIME,
+ &now);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ /* Convert from timespec to timeval */
+ tv->tv_sec = now.tv_sec;
+ tv->tv_usec = now.tv_nsec / 1000;
+ }
+ return ret;
+#else
+# ifdef __NR_clock_nanosleep_time64
+ long int ret;
+# if __TIMESIZE == 64
+ ret = INLINE_VSYSCALL (clock_gettime64, 2, CLOCK_REALTIME,
+ &now);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ /* Convert from timespec to timeval */
+ tv->tv_sec = now.tv_sec;
+ tv->tv_usec = now.tv_nsec / 1000;
+ return ret;
+ }
+# else
+ struct __timespec64 now;
+
+ ret = INLINE_VSYSCALL (clock_gettime64, 2, CLOCK_REALTIME,
+ &now);
+
+ if (ret == 0 || errno != ENOSYS)
+ {
+ /* Convert from timespec to timeval */
+ tv->tv_sec = now.tv_sec;
+ tv->tv_usec = now.tv_nsec / 1000;
+ return ret;
+ }
+# endif /* __TIMESIZE == 64 */
+# endif /* __NR_clock_nanosleep_time64 */
+# if __TIMESIZE == 64
+ if (! in_time_t_range (tv->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+# endif /* __TIMESIZE == 64 */
return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+#endif
}
libc_hidden_def (__gettimeofday)
weak_alias (__gettimeofday, gettimeofday)
Not all architectures support the obsolete gettimeofday so use the newer clock_gettime64 syscall if it is avaliable. This fixes RV32 build issues. This has the side effect of not setting the struct timezone *tz variable if __ASSUME_TIME64_SYSCALLS or __NR_clock_gettime64 is defined!!! The struct timezone *tz variable contaions information on the current timezone, in this structure: struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of DST correction */ }; On 32-bit systems with __ARCH_WANT_TIME32_SYSCALLS not defined there is no way way to get the struct timezone via a syscall. AFAIK there are no plans to add suppor to a future kernel. The Linux documentation says that "The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL." Most callers of gettimeofday() don't use the timezone data, see example code from Debian below. If __ASSUME_TIME64_SYSCALLS and __NR_clock_gettime64 are not defined then struct timezone *tz will be set as usual. Example code from Debian: struct timeval my_gettime(void) { struct timezone tz_ignored; struct timeval tv; gettimeofday(&tv, &tz_ignored); return tv; } Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- ChangeLog | 1 + sysdeps/unix/sysv/linux/gettimeofday.c | 51 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+)