Y2038: add function __clock_getres_time64
Commit Message
* include/time.h (__clock_getres_time64): Add.
* sysdeps/posix/clock_getres.c (hp_timing_getres): Use
struct __timespec64.
* sysdeps/posix/clock_getres.c (realtime_getres): Likewise.
* sysdeps/posix/clock_getres.c (__clock_getres_time64): Add.
* sysdeps/posix/clock_getres.c Use SYSDEP_GETRES64.
* sysdeps/posix/clock_getres.c Use SYSDEP_GETRES_CPU64.
* sysdeps/posix/clock_getres.c (__clock_getres):
Use __clock_getres_time64.
* sysdeps/unix/sysv/linux/clock_getres.c (SYSCALL_GETRES32): Add.
* sysdeps/unix/sysv/linux/clock_getres.c (SYSCALL_GETRES64): Likewise.
* sysdeps/unix/sysv/linux/clock_getres.c (SYSDEP_GETRES64): Likewise.
* sysdeps/unix/sysv/linux/clock_getres.c (SYSDEP_GETRES_CPU64): Likewise.
---
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_getres_time64
syscall being provided by the kernel at build as well
as run time.
This patch is part of the Y2038 patch series, which is available at
<https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/aaribaud/y2038>.
Warning: this branch may be rebased on current master and/or updated based on
feedback from the list at any time.
include/time.h | 2 +
sysdeps/posix/clock_getres.c | 31 +++++++++----
sysdeps/unix/sysv/linux/clock_getres.c | 61 ++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 9 deletions(-)
Comments
On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:
> @@ -23,12 +23,11 @@
> #include <sys/param.h>
> #include <libc-internal.h>
>
> -
> #if HP_TIMING_AVAIL
Please avoid spurious diff hunks adding or removing whitespace like this.
> +int
> +__clock_getres (clockid_t clock_id, struct timespec *res)
> +{
> + struct __timespec64 ts64;
> + int retval = __clock_getres_time64 (clock_id, &ts64);
> + if (retval == 0)
> + {
> + // We assume we never run with a CPU clock period greater than
> + // 2**31 seconds and therefore we do not check the seconds field
Comments in glibc should use /* */, not //. All comments should end with
".". Please check for and fix such issues throughout the patch series.
There are several others in this patch.
> + res->tv_sec = ts64.tv_sec;
> + res->tv_nsec = ts64.tv_nsec;
> + }
> + return retval;
Generically, it is important that on systems where time_t is already
64-bit, no additional conversion code or function calls get built into
glibc; the abstractions used at the source code level must be completely
optimized away in that case (whether through use of #if etc. to control
what gets built and what functions are aliases of what other functions, or
through arranging the code so it can and does all get inlined in that
case, etc.).
Please, in each patch posting, include details of the configurations for
which it was tested for the full glibc testsuite (which should include at
least one 32-bit and one 64-bit configuration). You should also include
explicit confirmation of how the code ensures no additional speed or size
overhead for configurations where time_t is already 64-bit.
@@ -28,6 +28,8 @@ extern int __clock_gettime64 (clockid_t __clock_id,
struct __timespec64 *__tp) __THROW;
extern int __clock_settime64 (clockid_t __clock_id,
const struct __timespec64 *__tp) __THROW;
+extern int __clock_getres_time64 (clockid_t __clock_id,
+ struct __timespec64 *__res) __THROW;
/* Now define the internal interfaces. */
struct tm;
@@ -23,12 +23,11 @@
#include <sys/param.h>
#include <libc-internal.h>
-
#if HP_TIMING_AVAIL
static long int nsec; /* Clock frequency of the processor. */
static int
-hp_timing_getres (struct timespec *res)
+hp_timing_getres (struct __timespec64 *res)
{
if (__glibc_unlikely (nsec == 0))
{
@@ -56,7 +55,7 @@ hp_timing_getres (struct timespec *res)
#endif
static inline int
-realtime_getres (struct timespec *res)
+realtime_getres (struct __timespec64 *res)
{
long int clk_tck = __sysconf (_SC_CLK_TCK);
@@ -73,17 +72,16 @@ realtime_getres (struct timespec *res)
return -1;
}
-
/* Get resolution of clock. */
int
-__clock_getres (clockid_t clock_id, struct timespec *res)
+__clock_getres_time64 (clockid_t clock_id, struct __timespec64 *res)
{
int retval = -1;
switch (clock_id)
{
-#ifdef SYSDEP_GETRES
- SYSDEP_GETRES;
+#ifdef SYSDEP_GETRES64
+ SYSDEP_GETRES64;
#endif
#ifndef HANDLED_REALTIME
@@ -93,8 +91,8 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
#endif /* handled REALTIME */
default:
-#ifdef SYSDEP_GETRES_CPU
- SYSDEP_GETRES_CPU;
+#ifdef SYSDEP_GETRES_CPU64
+ SYSDEP_GETRES_CPU64;
#endif
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
@@ -115,4 +113,19 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
return retval;
}
+
+int
+__clock_getres (clockid_t clock_id, struct timespec *res)
+{
+ struct __timespec64 ts64;
+ int retval = __clock_getres_time64 (clock_id, &ts64);
+ if (retval == 0)
+ {
+ // We assume we never run with a CPU clock period greater than
+ // 2**31 seconds and therefore we do not check the seconds field
+ res->tv_sec = ts64.tv_sec;
+ res->tv_nsec = ts64.tv_nsec;
+ }
+ return retval;
+}
weak_alias (__clock_getres, clock_getres)
@@ -19,6 +19,7 @@
#include <sysdep.h>
#include <errno.h>
#include <time.h>
+#include <y2038-support.h>
#include "kernel-posix-cpu-timers.h"
#ifdef HAVE_CLOCK_GETRES_VSYSCALL
@@ -48,4 +49,64 @@
#define SYSDEP_GETRES_CPU SYSCALL_GETRES
#define SYSDEP_GETRES_CPUTIME /* Default catches them too. */
+/* The 64-bit version */
+
+// Call the 32-bit syscall and convert to 64-bit time
+#define SYSCALL_GETRES32 \
+ retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32); \
+ if (retval==0) \
+ { \
+ timespec_to_timespec64(&ts32, res); \
+ res->tv_pad = 0; \
+ }
+
+#ifdef __NR_clock_getres_time64
+
+/* We are building with a 64-bit-time getres syscall */
+
+#define SYSCALL_GETRES64 \
+ if (__y2038_linux_support > 0) \
+ { \
+ retval = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res); \
+ if (retval == -1 && errno == ENOSYS) \
+ { \
+ __y2038_linux_support = -1; \
+ SYSCALL_GETRES32; \
+ } \
+ } \
+ else \
+ { \
+ SYSCALL_GETRES32; \
+ } \
+ break
+
+#else
+
+/* We are building without a 64-bit-time getres syscall */
+
+#define SYSCALL_GETRES64 \
+ SYSCALL_GETRES32; \
+ break
+
+#endif
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+ kernel. */
+#define SYSDEP_GETRES64 \
+ SYSDEP_GETRES_CPUTIME64 \
+ case CLOCK_REALTIME: \
+ case CLOCK_MONOTONIC: \
+ case CLOCK_MONOTONIC_RAW: \
+ case CLOCK_REALTIME_COARSE: \
+ case CLOCK_MONOTONIC_COARSE: \
+ SYSCALL_GETRES64
+
+/* We handled the REALTIME clock here. */
+#define HANDLED_REALTIME64 1
+#define HANDLED_CPUTIME64 1
+
+#define SYSDEP_GETRES_CPU64 SYSCALL_GETRES64
+#define SYSDEP_GETRES_CPUTIME64 \
+ struct timespec ts32;
+
#include <sysdeps/posix/clock_getres.c>