From patchwork Sun Oct 20 21:38:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukasz Majewski X-Patchwork-Id: 35193 Received: (qmail 79891 invoked by alias); 20 Oct 2019 21:39:52 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 79880 invoked by uid 89); 20 Oct 2019 21:39:52 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 spammy=applicable, Compute, errno, Run X-HELO: mail-out.m-online.net From: Lukasz Majewski To: Joseph Myers , Paul Eggert Cc: Alistair Francis , Arnd Bergmann , Alistair Francis , GNU C Library , Adhemerval Zanella , Florian Weimer , Carlos O'Donell , Stepan Golosunov , Florian Weimer , Zack Weinberg , Lukasz Majewski Subject: [PATCH v2] y2038: linux: Provide __clock_getres64 implementation Date: Sun, 20 Oct 2019 23:38:59 +0200 Message-Id: <20191020213859.15952-1-lukma@denx.de> MIME-Version: 1.0 This patch provides new __clock_getres64 explicit 64 bit function for getting the resolution (precision) of specified clock ID. Moreover, a 32 bit version - __clock_getres has been refactored to internally use __clock_getres64. The __clock_getres is now supposed to be used on systems still supporting 32 bit time (__TIMESIZE != 64) - hence the necessary conversion from 64 bit struct __timespec64 to struct timespec. The new clock_getres_time64 syscall available from Linux 5.1+ has been used, when applicable. On systems which are not supporting clock_getres_time64 (as their clock_getres supports 64 bit time ABI) the vDSO syscall is attempted. On the contrary the non-vDSO syscall is used for clock_getres_time64 as up till now the kernel is not providing such interface. No additional checks (i.e. if tv_nsec value overflow) are performed on values returned via clock_getres{_time64} syscall, as it is assumed that the Linux kernel will either return 0 and provide correct value or error. The check for tv_sec being out of range on systems still supporting 32 bit time (__TIMESIZE != 64) without Y2038 time support is also omitted as it is _very_ unlikely that we would have a timer with resolution which exceeds 32 bit time_t range. Build tests: - The code has been tested on x86_64/x86 (native compilation): make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8" - The glibc has been build tested (make PARALLELMFLAGS="-j8") for x86 (i386), x86_64-x32, and armv7 Run-time tests: - Run specific tests on ARM/x86 32bit systems (qemu): https://github.com/lmajewski/meta-y2038 and run tests: https://github.com/lmajewski/y2038-tests/commits/master - Use of cross-test-ssh.sh for ARM (armv7): make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh root@192.168.7.2' xcheck Linux kernel, headers and minimal kernel version for glibc build test matrix: - Linux v5.1 (with clock_getres_time64) and glibc build with v5.1 as minimal kernel version (--enable-kernel="5.1.0") The __ASSUME_TIME64_SYSCALLS flag defined. - Linux v5.1 and default minimal kernel version The __ASSUME_TIME64_SYSCALLS not defined, but kernel supports clock_getres_time64 syscall. - Linux v4.19 (no clock_getres_time64 support) with default minimal kernel version for contemporary glibc This kernel doesn't support clock_getres_time64 syscall, so the fallback to clock_getres is tested. The above tests were performed with Y2038 redirection applied as well as without (so the __TIMESIZE != 64 execution path is checked as well). No regressions were observed. --- Changes for v2: - Replace timespec64_to_timespec () with valid_timespec64_to_timespec () as clock_getres() just reads the value from the kernel. Therefore one can assume that if the syscall returns 0, the value passed from the kernel is correct and no extra checks are necessary. --- include/time.h | 8 ++++++ sysdeps/unix/sysv/linux/clock_getres.c | 38 ++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/include/time.h b/include/time.h index d93b16a781..8a21350233 100644 --- a/include/time.h +++ b/include/time.h @@ -133,6 +133,14 @@ extern int __clock_settime64 (clockid_t clock_id, libc_hidden_proto (__clock_settime64) #endif +#if __TIMESIZE == 64 +# define __clock_getres64 __clock_getres +#else +extern int __clock_getres64 (clockid_t clock_id, + struct __timespec64 *tp); +libc_hidden_proto (__clock_getres64); +#endif + /* Compute the `struct tm' representation of T, offset OFFSET seconds east of UTC, and store year, yday, mon, mday, wday, hour, min, sec into *TP. diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c index 0b82759043..22762608be 100644 --- a/sysdeps/unix/sysv/linux/clock_getres.c +++ b/sysdeps/unix/sysv/linux/clock_getres.c @@ -19,21 +19,53 @@ #include #include #include -#include "kernel-posix-cpu-timers.h" #ifdef HAVE_CLOCK_GETRES_VSYSCALL # define HAVE_VSYSCALL #endif #include - #include +#include /* Get resolution of clock. */ int -__clock_getres (clockid_t clock_id, struct timespec *res) +__clock_getres64 (clockid_t clock_id, struct __timespec64 *res) { +#ifdef __ASSUME_TIME64_SYSCALLS +# ifndef __NR_clock_getres_time64 return INLINE_VSYSCALL (clock_getres, 2, clock_id, res); +# else + return INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res); +# endif +#else +# ifdef __NR_clock_getres_time64 + int ret = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res); + if (ret == 0 || errno != ENOSYS) + return ret; +# endif + struct timespec ts32; + int retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32); + if (! retval && res) + *res = valid_timespec_to_timespec64 (ts32); + + return retval; +#endif +} + +#if __TIMESIZE != 64 +int +__clock_getres (clockid_t clock_id, struct timespec *res) +{ + struct __timespec64 ts64; + int retval; + + retval = __clock_getres64 (clock_id, &ts64); + if (! retval && res) + *res = valid_timespec64_to_timespec (ts64); + + return retval; } +#endif versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); /* clock_getres moved to libc in version 2.17;