diff mbox series

[5/6] y2038: linux: Provide __clock_gettime64 implementation

Message ID 20190414220841.20243-6-lukma@denx.de
State New
Headers show
Series y2038: Linux: Provide __clock_* functions supporting 64 bit time | expand

Commit Message

Lukasz Majewski April 14, 2019, 10:08 p.m. UTC
This patch provides new __clock_gettime64 explicit 64 bit function for
getting the value of specified clock ID. Moreover, a
32 bit version - __clock_gettime has been refactored to internally use
__clock_gettime64.

The __clock_gettime is now supposed to be used on 32 bit systems -
hence the necessary checks and conversion to 64 bit type. After this
change it is intrinsically Y2038 safe.

The new 64 bit syscall (clock_gettime64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected
in any way.

Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"

- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.

No regressions were observed.

* include/time.h (__clock_gettime64):
  Add __clock_gettime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime):
  Refactor this function to be used only on 32 bit machines as a
  wrapper on __clock_gettime64.
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64): Add
* sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime64):
  Use clock_gettime64 kernel syscall (available from 5.1-rc1+
  Linux) by 32 bit Y2038 safe systems
---
 include/time.h                          |  8 ++++++++
 sysdeps/unix/sysv/linux/clock_gettime.c | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/include/time.h b/include/time.h
index 20b9974078..7176ddbb84 100644
--- a/include/time.h
+++ b/include/time.h
@@ -133,6 +133,14 @@  libc_hidden_proto (__clock_settime64)
 #endif
 
 #if __TIMESIZE == 64
+# define __clock_gettime64 __clock_gettime
+#else
+extern int __clock_gettime64 (clockid_t clock_id,
+                              struct __timespec64 *tp);
+libc_hidden_proto (__clock_gettime64);
+#endif
+
+#if __TIMESIZE == 64
 # define __clock_getres64 __clock_getres
 #else
 extern int __clock_getres64 (clockid_t clock_id,
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index 5fc47fb7dc..fd94c6fec4 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -28,9 +28,40 @@ 
 
 /* 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)
 {
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_gettime64
+  return INLINE_SYSCALL_CALL (clock_gettime64, clock_id, tp);
+# else
+  struct timespec ts32;
+  int retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);
+  if (! retval)
+    valid_timespec_to_timespec64(&ts32, tp);
+
+  return retval;
+# endif
+#else
   return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);
+#endif
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+#if __TIMESIZE != 64
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+  struct __timespec64 ts64;
+  int retval;
+
+  retval = __clock_gettime64 (clock_id, &ts64);
+  if (! retval && ! timespec64_to_timespec (&ts64, tp))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return retval;
+}
+#endif