[RFC,06/52] Y2038: add struct __timespec64

Message ID 20170907224219.12483-7-albert.aribaud@3adev.fr
State New
Headers show
Series
  • Make GLIBC Y2038-proof
Related show

Commit Message

Albert ARIBAUD Sept. 7, 2017, 10:41 p.m.
To be Y2038-proof, struct __timespec64 needs its tv_sec field to
be a __time64_t rather than a __time_t. However, the question is
which type should the tv_nsec field be.

Keeping tv_nsec a long (32-bit) would be compatible with Posix
requirements but would result in the GLIBC struct timespec being
binary-incompatible with the Linux 64-bit struct timespec, which
contains a 64-bit, not 32-bit, signed tv_nsec field.

In order to maintain Posix compatibility yet simplify conversion
between Posix and Linux struct timespec values, the Y2038-proof
struct time stores its tv_nsec field as a 32-bit signed integer
plus a padding which can serve as a 64-bit sign extension. This
both meets Posix requirements and makes the GLIBC and Linux
struct timespec binary compatible.

Note that in the API (which is not modified here, and will be
later alongside all Y2038-sensitive APIs), this padding is made
'invisible' by defining it as an anonymous bitfield; whereas
the struct __timespec64 introduced here has a named field for
the padding, allowing implementations to read and write it.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

Patch

diff --git a/include/time.h b/include/time.h
index 79ab6ab6a1..c436c44539 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,8 @@ 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
 
+#include <endian.h>
+
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
 extern __typeof (strptime_l) __strptime_l;
@@ -18,6 +20,22 @@  libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+#if BYTE_ORDER == BIG_ENDIAN
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+};
+#else
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+};
+#endif
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)