Y2038: add function __clock_gettime64
Commit Message
* include/time.h: Declare __clock_gettime64().
* ntpl/pthread_clock_gettime.c: Add __pthread_clock_gettime64().
* ntpl/pthread_clock_gettime.c: Make __pthread_clock_gettime()
a wrapper around __pthread_clock_gettime64().
* sysdeps/unix/clock_gettime.c (hp_timing_gettime): Use struct
__timespec64.
* sysdeps/unix/clock_gettime.c (realtime_gettime): Likewise.
* sysdeps/unix/clock_gettime.c: Add __clock_gettime64().
* sysdeps/unix/clock_gettime.c: Make __clock_gettime() a
wrapper around __clock_gettime64().
* sysdeps/unix/sysv/linux/clock_gettime.c: Add 64-bit-time syscall
support.
---
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 | 3 ++
nptl/pthread_clock_gettime.c | 37 ++++++++++++++++++-
sysdeps/unix/clock_gettime.c | 49 ++++++++++++++++++++-----
sysdeps/unix/sysv/linux/clock_gettime.c | 43 ++++++++++++++++++++--
4 files changed, 118 insertions(+), 14 deletions(-)
Comments
On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:
> + set_errno(EOVERFLOW);
Note GNU style has a space before the open parenthesis.
> +# define DO_CLOCK_GETTIME_64 \
> + if (__y2038_linux_support > 0) \
> + { \
> + retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
> + if (retval == -1 && errno == ENOSYS) \
> + { \
> + __y2038_linux_support = -1; \
> + DO_CLOCK_GETTIME_32; \
> + } \
> + } \
> + else \
> + { \
> + DO_CLOCK_GETTIME_32; \
> + }
Such macros need to be designed in such a way that the runtime ENOSYS
check, and the assignment to __y2038_linux_support, are optimized away at
compile time given the __ASSUME_* macro for the 64-bit time syscalls.
On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:
> 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.
This is the complete human-level description for this patch. That's
simply not enough; you need to say something more about the overall nature
of the changes in the patch, not just what series it comes from. (That
is, discuss what functions are changing to use 64-bit times internally,
with the time_t APIs becoming wrappers round them, when time_t is 32-bit,
or aliases for them, when time_t is already 64-bit. And as usual,
describe the platforms on which testing was done.)
(The above paragraph, referencing a patch series that may be rebased, is
not appropriate for inclusion in the commit message itself at all - it's
reasonable for the patch email, as long as it's clear it's not part of the
intended commit message, much like a description of changes between two
versions of a patch also goes in a patch submission email but not the
final commit message. But commit messages need to make sense at any time
in the future, and so can't rely on information from branches that are
going to be rebased.)
@@ -24,6 +24,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;
@@ -18,13 +18,14 @@
#include <errno.h>
#include <stdlib.h>
#include <time.h>
+#include <bits/types/struct_timespec64.h>
#include "pthreadP.h"
#if HP_TIMING_AVAIL
int
-__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
- struct timespec *tp)
+__pthread_clock_gettime64 (clockid_t clock_id, hp_timing_t freq,
+ struct __timespec64 *tp)
{
hp_timing_t tsc;
@@ -64,4 +65,36 @@ __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
return 0;
}
+
+int
+__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
+ struct timespec *tp)
+{
+ struct __timespec64 ts64;
+ int res;
+
+ if (tp == NULL)
+ {
+ __set_errno(EINVAL);
+ res = -1;
+ }
+ else
+ {
+ int res = __pthread_clock_gettime64 (clock_id, freq, &ts64);
+ if (res == 0)
+ {
+ if (fits_in_time_t (ts64.tv_time))
+ {
+ tp->tv_sec = ts64.tv_sec;
+ tp->tv_nsec = ts64.tv_nsec;
+ }
+ else
+ {
+ set_errno(EOVERFLOW);
+ res = -1;
+ }
+ }
+ }
+ return res;
+}
#endif
@@ -32,12 +32,12 @@ static hp_timing_t freq;
/* This function is defined in the thread library. */
-extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
- struct timespec *tp)
+extern int __pthread_clock_gettime64 (clockid_t clock_id, hp_timing_t freq,
+ struct __timespec64 *tp)
__attribute__ ((__weak__));
static int
-hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
+hp_timing_gettime (clockid_t clock_id, struct __timespec64 *tp)
{
hp_timing_t tsc;
@@ -55,7 +55,7 @@ hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
if (clock_id != CLOCK_PROCESS_CPUTIME_ID
&& __pthread_clock_gettime != NULL)
- return __pthread_clock_gettime (clock_id, freq, tp);
+ return __pthread_clock_gettime64 (clock_id, freq, tp);
/* Get the current counter. */
HP_TIMING_NOW (tsc);
@@ -76,20 +76,20 @@ hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
static inline int
-realtime_gettime (struct timespec *tp)
+realtime_gettime (struct __timespec64 *tp)
{
struct timeval tv;
int retval = __gettimeofday (&tv, NULL);
if (retval == 0)
/* Convert into `timespec'. */
- TIMEVAL_TO_TIMESPEC (&tv, tp);
+ valid_timeval_to_timespec64 (&tv, tp);
return retval;
}
/* Get current value of CLOCK and store it in TP. */
int
-__clock_gettime (clockid_t clock_id, struct timespec *tp)
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
{
int retval = -1;
@@ -103,9 +103,9 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
case CLOCK_REALTIME:
{
struct timeval tv;
- retval = __gettimeofday (&tv, NULL);
+ retval = __gettimeofday (&tv32, NULL);
if (retval == 0)
- TIMEVAL_TO_TIMESPEC (&tv, tp);
+ valid_timeval_to_timespec64 (&tv32, tp);
}
break;
#endif
@@ -132,5 +132,36 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
return retval;
}
+
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ struct __timespec64 ts64;
+ int res;
+
+ if (tp == NULL)
+ {
+ __set_errno(EINVAL);
+ res = -1;
+ }
+ else
+ {
+ res = __clock_gettime64 (clock_id, &ts64);
+ if (res == 0)
+ {
+ if (fits_in_time_t (ts64.tv_sec))
+ {
+ tp->tv_sec = ts64.tv_sec;
+ tp->tv_nsec = ts64.tv_nsec;
+ }
+ else
+ {
+ __set_errno(EOVERFLOW);
+ res = -1;
+ }
+ }
+ }
+ return res;
+}
weak_alias (__clock_gettime, clock_gettime)
libc_hidden_def (__clock_gettime)
@@ -25,6 +25,41 @@
# define HAVE_VSYSCALL
#endif
#include <sysdep-vdso.h>
+#include <y2038-support.h>
+
+# define DO_CLOCK_GETTIME_32 \
+ retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \
+ if (retval == 0) \
+ { \
+ valid_timespec_to_timespec64 (&ts32, tp); \
+ }
+
+#ifdef __NR_clock_gettime64
+
+/* We are building with a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_GETTIME_64 \
+ if (__y2038_linux_support > 0) \
+ { \
+ retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
+ if (retval == -1 && errno == ENOSYS) \
+ { \
+ __y2038_linux_support = -1; \
+ DO_CLOCK_GETTIME_32; \
+ } \
+ } \
+ else \
+ { \
+ DO_CLOCK_GETTIME_32; \
+ }
+
+#else
+
+/* We are building without a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_GETTIME_64 DO_CLOCK_GETTIME_32
+
+#endif
/* The REALTIME and MONOTONIC clock are definitely supported in the
kernel. */
@@ -32,7 +67,7 @@
SYSDEP_GETTIME_CPUTIME; \
case CLOCK_REALTIME: \
case CLOCK_MONOTONIC: \
- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
+ DO_CLOCK_GETTIME_64; \
break
/* We handled the REALTIME clock here. */
@@ -40,8 +75,10 @@
#define HANDLED_CPUTIME 1
#define SYSDEP_GETTIME_CPU(clock_id, tp) \
- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
+ DO_CLOCK_GETTIME_64; \
break
-#define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */
+
+#define SYSDEP_GETTIME_CPUTIME \
+ struct timespec ts32
#include <sysdeps/unix/clock_gettime.c>