From patchwork Wed Apr 18 20:17:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Albert ARIBAUD X-Patchwork-Id: 26792 Received: (qmail 103916 invoked by alias); 18 Apr 2018 20:19:32 -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 103807 invoked by uid 89); 18 Apr 2018 20:19:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, RCVD_IN_RP_RNBL autolearn=ham version=3.3.2 spammy=2111 X-HELO: smtp3-g21.free.fr From: "Albert ARIBAUD (3ADEV)" To: libc-alpha@sourceware.org Cc: "Albert ARIBAUD (3ADEV)" Subject: [[PATCH RFC 2] 13/63] Y2038: add function __clock_gettime64 Date: Wed, 18 Apr 2018 22:17:29 +0200 Message-Id: <20180418201819.15952-14-albert.aribaud@3adev.fr> In-Reply-To: <20180418201819.15952-13-albert.aribaud@3adev.fr> References: <20180418201819.15952-1-albert.aribaud@3adev.fr> <20180418201819.15952-2-albert.aribaud@3adev.fr> <20180418201819.15952-3-albert.aribaud@3adev.fr> <20180418201819.15952-4-albert.aribaud@3adev.fr> <20180418201819.15952-5-albert.aribaud@3adev.fr> <20180418201819.15952-6-albert.aribaud@3adev.fr> <20180418201819.15952-7-albert.aribaud@3adev.fr> <20180418201819.15952-8-albert.aribaud@3adev.fr> <20180418201819.15952-9-albert.aribaud@3adev.fr> <20180418201819.15952-10-albert.aribaud@3adev.fr> <20180418201819.15952-11-albert.aribaud@3adev.fr> <20180418201819.15952-12-albert.aribaud@3adev.fr> <20180418201819.15952-13-albert.aribaud@3adev.fr> The Unix implementation uses 32-bit calls and converts to 64-bit time. The Linux implementation uses the 64-bit time syscall if available, otherwise it falls back to 32-bit syscall and conversion. This implementation depends on the clock_gettime64 syscall being provided in the kernel headers at build time. --- include/time.h | 8 ++++ sysdeps/unix/clock_gettime.c | 54 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/clock_gettime.c | 81 +++++++++++++++++++++++++++++++++ time/Versions | 3 ++ 4 files changed, 146 insertions(+) diff --git a/include/time.h b/include/time.h index 16286178e1..e085fa5162 100644 --- a/include/time.h +++ b/include/time.h @@ -21,6 +21,11 @@ libc_hidden_proto (strptime) libc_hidden_proto (__localtime64) +/* Indicates whether the underlying kernel has 64-bit time support. + This is required for e.g. librt, which cannot directly check the + flag variable that init-first.c sets when detecting support. */ +extern int __y2038_kernel_support (void); + extern __typeof (clock_getres) __clock_getres; extern __typeof (clock_gettime) __clock_gettime; libc_hidden_proto (__clock_gettime) @@ -28,6 +33,9 @@ extern __typeof (clock_settime) __clock_settime; extern __typeof (clock_nanosleep) __clock_nanosleep; extern __typeof (clock_getcpuclockid) __clock_getcpuclockid; +extern int __clock_gettime64 (clockid_t __clock_id, + struct __timespec64 *__tp) __THROW; + /* Now define the internal interfaces. */ struct tm; diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c index 96df78ab1e..f8e96487e3 100644 --- a/sysdeps/unix/clock_gettime.c +++ b/sysdeps/unix/clock_gettime.c @@ -134,3 +134,57 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) } weak_alias (__clock_gettime, clock_gettime) libc_hidden_def (__clock_gettime) + +/* Get current value of CLOCK and store it in TP, 64-bit version. */ +int +__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp) +{ + int retval = -1; +#if HP_TIMING_AVAIL || !defined HANDLED_REALTIME + struct timeval tv32; +#endif + + switch (clock_id) + { +#ifdef SYSDEP_GETTIME64 + SYSDEP_GETTIME64; +#endif + +#ifndef HANDLED_REALTIME + case CLOCK_REALTIME: + { + retval = gettimeofday (&tv32, NULL); + if (retval == 0) + valid_timeval_to_timespec64 (&tv32, tp); + } + break; +#endif + + default: +#ifdef SYSDEP_GETTIME64_CPU + SYSDEP_GETTIME64_CPU (clock_id, tp); +#endif +#if HP_TIMING_AVAIL + if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) + == CLOCK_THREAD_CPUTIME_ID) + { + retval = hp_timing_gettime (clock_id, &tv32); + if (retval == 0) + valid_timeval_to_timespec64 (&tv32, tp); + } + else +#endif + __set_errno (EINVAL); + break; + +#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME + case CLOCK_PROCESS_CPUTIME_ID: + retval = hp_timing_gettime (clock_id, &tv32); + if (retval == 0) + valid_timeval_to_timespec64 (&tv32, tp); + break; +#endif + } + + return retval; +} diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c index d837fa36b1..a0da479ea6 100644 --- a/sysdeps/unix/sysv/linux/clock_gettime.c +++ b/sysdeps/unix/sysv/linux/clock_gettime.c @@ -44,4 +44,85 @@ break #define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */ +/* 64-bit versions */ + +/* Check that we are builing on a 64-bit-time kernel, otherwise + clock_gettime64 syscall will fail to compile */ +#ifdef __NR_clock_gettime64 + +/* The REALTIME and MONOTONIC clock are definitely supported in the + kernel. */ +#define SYSDEP_GETTIME64 \ + SYSDEP_GETTIME64_CPUTIME; \ + case CLOCK_REALTIME: \ + case CLOCK_MONOTONIC: \ + if (__y2038_linux_support) \ + { \ + retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); \ + } \ + else \ + { \ + retval = -1; \ + __set_errno(ENOSYS); \ + } \ + if (retval == -1 && errno == ENOSYS) \ + { \ + retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \ + if (retval==0) \ + { \ + valid_timespec_to_timespec64(&ts32, tp); \ + } \ + } \ + break + +#define SYSDEP_GETTIME64_CPU(clock_id, tp) \ + if (__y2038_linux_support) \ + { \ + retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); \ + } \ + else \ + { \ + retval = -1; \ + __set_errno(ENOSYS); \ + } \ + if (retval == -1 && errno == ENOSYS) \ + { \ + retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \ + if (retval==0) \ + { \ + valid_timespec_to_timespec64(&ts32, tp); \ + } \ + } \ + break +#define SYSDEP_GETTIME64_CPUTIME \ + struct timespec ts32; \ + extern int __y2038_linux_support; + +#else + +/* The REALTIME and MONOTONIC clock are definitely supported in the + kernel. */ +#define SYSDEP_GETTIME64 \ + SYSDEP_GETTIME64_CPUTIME; \ + case CLOCK_REALTIME: \ + case CLOCK_MONOTONIC: \ + retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \ + if (retval==0) \ + { \ + valid_timespec_to_timespec64(&ts32, tp); \ + } \ + break + +#define SYSDEP_GETTIME64_CPU(clock_id, tp) \ + retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \ + if (retval==0) \ + { \ + valid_timespec_to_timespec64(&ts32, tp); \ + } \ + break +#define SYSDEP_GETTIME64_CPUTIME \ + struct timespec ts32; \ + +#endif + #include diff --git a/time/Versions b/time/Versions index 7cfae8760c..27c46fc023 100644 --- a/time/Versions +++ b/time/Versions @@ -72,5 +72,8 @@ libc { __localtime64; __localtime64_r; __mktime64; __timelocal64_r; __timegm64; + __clock_gettime64; + __vdso_clock_gettime64; + __y2038_kernel_support; } }