[RFC,v4,03/24] sysdeps/gettimeofday: Use clock_gettime64 if avaliable
Commit Message
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(+)
Comments
On Fri, 9 Aug 2019, Alistair Francis wrote:
> The Linux documentation says that "The use of the timezone structure
> is obsolete; the tz argument should normally be specified as NULL."
The relevant information to include in commit messages here isn't what the
documentation says, it's what the interfaces actually do, as detailed in
<https://sourceware.org/ml/libc-alpha/2019-07/msg00574.html>.
> __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);
This is using a timespec (possibly 32-bit) with a syscall that requires
the 64-bit version. You need to address such issues throughout the patch
series. As illustrated here, it's not just cases where you have a
mismatch with the function interface; you need to make sure, in every
case, that where you pass internal variables to 64-bit time syscalls they
have the correct type as well.
> +#else
> +# ifdef __NR_clock_nanosleep_time64
No, this code isn't using clock_nanosleep_time64. The #ifdef should be
for the syscall it actually uses.
@@ -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)