[2/2] y2038: linux: Provide __timespec_get64 implementation

Message ID 20200116132728.11646-2-lukma@denx.de
State Superseded
Headers

Commit Message

Lukasz Majewski Jan. 16, 2020, 1:27 p.m. UTC
  This patch provides new __timespec_get64 explicit 64 bit function for getting
64 bit time in the struct __timespec64 (for compilation supporting C11).
Moreover, a 32 bit version - __timespec_get has been refactored to internally
use __timespec_get64.

The __timespec_get is now supposed to be used on systems still supporting 32
bit time (__TIMESIZE != 64) - hence the necessary conversion to 32 bit struct
timespec.

Internally the timespec_get uses __clock_gettime64. This patch is necessary
for having architectures with __WORDSIZE == 32 Y2038 safe.

Build tests:
./src/scripts/build-many-glibcs.py glibcs

Run-time tests:
- 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

Above tests were performed with Y2038 redirection applied as well as without
to test proper usage of both __timespec_get64 and __timespec_get.
---
 include/time.h      |  3 +++
 time/timespec_get.c | 33 ++++++++++++++++++++++++++++++---
 2 files changed, 33 insertions(+), 3 deletions(-)
  

Patch

diff --git a/include/time.h b/include/time.h
index 558923274a..047f431a1a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -254,6 +254,7 @@  extern double __difftime (time_t time1, time_t time0);
 #if __TIMESIZE == 64
 # define __clock_nanosleep_time64 __clock_nanosleep
 # define __clock_gettime64 __clock_gettime
+# define __timespec_get64 __timespec_get
 #else
 extern int __clock_nanosleep_time64 (clockid_t clock_id,
                                      int flags, const struct __timespec64 *req,
@@ -261,6 +262,8 @@  extern int __clock_nanosleep_time64 (clockid_t clock_id,
 libc_hidden_proto (__clock_nanosleep_time64)
 extern int __clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp);
 libc_hidden_proto (__clock_gettime64)
+extern int __timespec_get64 (struct __timespec64 *ts, int base);
+libc_hidden_proto (__timespec_get64)
 #endif
 
 /* Use in the clock_* functions.  Size of the field representing the
diff --git a/time/timespec_get.c b/time/timespec_get.c
index a1ec4167da..98f0aaf700 100644
--- a/time/timespec_get.c
+++ b/time/timespec_get.c
@@ -16,16 +16,43 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <time.h>
-
+#include <errno.h>
 
 /* Set TS to calendar time based in time base BASE.  */
 int
-timespec_get (struct timespec *ts, int base)
+__timespec_get64 (struct __timespec64 *ts, int base)
 {
   if (base == TIME_UTC)
     {
-      __clock_gettime (CLOCK_REALTIME, ts);
+      __clock_gettime64 (CLOCK_REALTIME, ts);
       return base;
     }
   return 0;
 }
+
+#if __TIMESIZE != 64
+libc_hidden_def (__timespec_get64)
+
+int
+__timespec_get (struct timespec *ts, int base)
+{
+  int ret;
+  struct __timespec64 tp64;
+
+  ret = __timespec_get64 (&tp64, base);
+
+  if (ret == TIME_UTC)
+    {
+      if (! in_time_t_range (tp64.tv_sec))
+        {
+          __set_errno (EOVERFLOW);
+          return 0;
+        }
+
+      *ts = valid_timespec64_to_timespec (tp64);
+    }
+
+  return ret;
+}
+#endif
+strong_alias (__timespec_get, timespec_get);