Y2038: add function __clock_gettime64

Message ID 20180919073400.27947-1-albert.aribaud@3adev.fr
State New, archived
Headers

Commit Message

Albert ARIBAUD Sept. 19, 2018, 7:34 a.m. UTC
  * 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

Joseph Myers Sept. 19, 2018, 1:13 p.m. UTC | #1
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.
  
Joseph Myers Sept. 19, 2018, 4:29 p.m. UTC | #2
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.)
  

Patch

diff --git a/include/time.h b/include/time.h
index 162afa1012..9efd153b83 100644
--- a/include/time.h
+++ b/include/time.h
@@ -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;
 
diff --git a/nptl/pthread_clock_gettime.c b/nptl/pthread_clock_gettime.c
index 6bc75cfe3f..508821b878 100644
--- a/nptl/pthread_clock_gettime.c
+++ b/nptl/pthread_clock_gettime.c
@@ -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
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 96df78ab1e..88c1955f17 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -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)
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index d837fa36b1..9920ffa1ab 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -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>