[RFC,v5,06/21] sysdeps/timespec_get: Use clock_gettime64 if avaliable

Message ID f723dfede07f251ab435a09b58adac51aef1e482.1567097252.git.alistair.francis@wdc.com
State New, archived
Headers

Commit Message

Alistair Francis Aug. 29, 2019, 4:50 p.m. UTC
  Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

	* sysdeps/unix/sysv/linux/timespec_get.c: Use clock_gettime64
	if avaliable.
---
 include/time.h                         |  1 +
 sysdeps/unix/sysv/linux/timespec_get.c | 48 ++++++++++++++++++++++++--
 2 files changed, 46 insertions(+), 3 deletions(-)
  

Patch

diff --git a/include/time.h b/include/time.h
index 1e33f34e1f6..ae88eac62d6 100644
--- a/include/time.h
+++ b/include/time.h
@@ -178,6 +178,7 @@  extern double __difftime (time_t time1, time_t time0);
 #define __nanosleep_time64 __nanosleep
 #define __nanosleep_nocancel_time64 __nanosleep_nocancel
 #define __clock_gettime64 __clock_gettime
+#define __timespec_get64 timespec_get
 #endif
 
 /* Use in the clock_* functions.  Size of the field representing the
diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 52080ddf08a..f53e75d5719 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -26,16 +26,34 @@ 
 
 /* Set TS to calendar time based in time base BASE.  */
 int
-timespec_get (struct timespec *ts, int base)
+__timespec_get64 (struct timespec *ts, int base)
 {
   switch (base)
     {
       int res;
       INTERNAL_SYSCALL_DECL (err);
     case TIME_UTC:
-      res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, ts);
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_gettime64
+#  define __NR_clock_gettime64 __NR_clock_gettime
+# endif
+      res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+#else
+# ifdef __NR_clock_gettime64
+      res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+# endif /* __NR_clock_gettime64 */
+      struct timespec ts32;
+
+      res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts32);
+
+      if (res == 0 || !INTERNAL_SYSCALL_ERROR_P (res, err))
+        {
+          ts->tv_sec = ts32.tv_sec;
+          ts->tv_nsec = ts32.tv_nsec;
+        }
+#endif
       if (INTERNAL_SYSCALL_ERROR_P (res, err))
-	return 0;
+        return 0;
       break;
 
     default:
@@ -44,3 +62,27 @@  timespec_get (struct timespec *ts, int base)
 
   return base;
 }
+
+#if __TIMESIZE != 64
+int
+timespec_get (struct timespec *ts, int base)
+{
+  int ret;
+  struct __timespec64 ts64;
+
+  ret = __timespec_get64 (&ts64, base);
+
+  if (ret == 0 || !INTERNAL_SYSCALL_ERROR_P (ret, err))
+    {
+      ts->tv_sec = ts64.tv_sec;
+      ts->tv_nsec = ts64.tv_nsec;
+      if (! in_time_t_range (ts64.tv_sec))
+        {
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+    }
+
+  return ret;
+}
+#endif