From ec138c67cbda8b5826a0a2a7ba456408117996dc Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 15 Jul 2019 16:30:59 -0700 Subject: [PATCH] sysdeps/clock_gettime: Use clock_gettime64 if avaliable With the clock_gettime64 call we prefer to use vDSO. There is no call to clock_gettime64 on glibc with older headers and kernel 5.1+ if it doesn't support vDSO. Reviewed-by: Adhemerval Zanella --- include/time.h | 3 ++ sysdeps/unix/sysv/linux/clock_gettime.c | 44 ++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/time.h b/include/time.h index d7800eb30f..c19c73ae09 100644 --- a/include/time.h +++ b/include/time.h @@ -211,11 +211,14 @@ extern double __difftime (time_t time1, time_t time0); #if __TIMESIZE == 64 # define __clock_nanosleep_time64 __clock_nanosleep +# define __clock_gettime64 __clock_gettime #else extern int __clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct __timespec64 *req, struct __timespec64 *rem); libc_hidden_proto (__clock_nanosleep_time64) +extern int __clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp); +libc_hidden_proto (__clock_gettime64) #endif /* Use in the clock_* functions. Size of the field representing the diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c index ca40983f6c..875c4fe905 100644 --- a/sysdeps/unix/sysv/linux/clock_gettime.c +++ b/sysdeps/unix/sysv/linux/clock_gettime.c @@ -17,6 +17,7 @@ . */ #include +#include #include #include #include "kernel-posix-cpu-timers.h" @@ -30,10 +31,51 @@ /* Get current value of CLOCK and store it in TP. */ int +__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp) +{ +#ifdef __ASSUME_TIME64_SYSCALLS +# ifndef __NR_clock_gettime64 +# define __NR_clock_gettime64 __NR_clock_gettime +# define __vdso_clock_gettime64 __vdso_clock_gettime +# endif + return INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); +#else +# if defined HAVE_CLOCK_GETTIME64_VSYSCALL + int ret64 = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); + if (ret64 == 0 || errno != ENOSYS) + return ret64; +# endif + struct timespec tp32; + int ret = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &tp32); + if (ret == 0) + *tp = valid_timespec_to_timespec64 (tp32); + return ret; +#endif +} + +#if __TIMESIZE != 64 +int __clock_gettime (clockid_t clock_id, struct timespec *tp) { - return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); + int ret; + struct __timespec64 tp64; + + ret = __clock_gettime64 (clock_id, &tp64); + + if (ret == 0) + { + if (! in_time_t_range (tp64.tv_sec)) + { + __set_errno (EOVERFLOW); + return -1; + } + + *tp = valid_timespec64_to_timespec (tp64); + } + + return ret; } +#endif libc_hidden_def (__clock_gettime) versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17);