This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC 1/7] y2038: Introduce struct __timespec64


This type is a glibc's type similar to struct timespec
but whose tv_sec field is a __time64_t rather than a time_t,
which makes it Y2038-proof and usable to pass between user
code and Y2038-proof kernel syscalls (e.g. clock_gettime()).

On 64-bit architectures, and on X32, struct __timespec64 is
just an alias of struct timespec, which is already 64-bit.
On other architectures, it must be explicitly defined.

When passing this structure to the kernel - it ensures that the
higher half of tv_nsec is always 0, which means that glibc
can reuse the public type (as tv_pad is zeroed anyway).

Moreover, the tv_nsec has an anonymous 32 bit padding (ordered
according to the endianness of the architecture) to prevent user space
programs, depending on long, 32 bit, tv_nsec from breaking.

Tested on x86_64 and ARM.

* time/bits/types/struct___timespec64.h:
  Create new file time/bits/types/struct___timespec64.h
* include/time.h: Add # include <time/bits/types/struct___timespec64.h>
* time/Makefile:
  Add bits/types/struct___timespec64.h to Makefile's headers
---
 include/time.h                        |  1 +
 time/Makefile                         |  2 +-
 time/bits/types/struct___timespec64.h | 39 +++++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+), 1 deletion(-)
 create mode 100644 time/bits/types/struct___timespec64.h

diff --git a/include/time.h b/include/time.h
index ac3163c2a5..d8a3ef35e2 100644
--- a/include/time.h
+++ b/include/time.h
@@ -5,6 +5,7 @@
 # include <bits/types/locale_t.h>
 # include <stdbool.h>
 # include <time/mktime-internal.h>
+# include <time/bits/types/struct___timespec64.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
diff --git a/time/Makefile b/time/Makefile
index 5c6304ece1..dc9ad55678 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -27,7 +27,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 	   bits/types/struct_itimerspec.h				\
 	   bits/types/struct_timespec.h bits/types/struct_timeval.h	\
 	   bits/types/struct_tm.h bits/types/timer_t.h			\
-	   bits/types/time_t.h
+	   bits/types/time_t.h bits/types/struct___timespec64.h
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
diff --git a/time/bits/types/struct___timespec64.h b/time/bits/types/struct___timespec64.h
new file mode 100644
index 0000000000..9946717af6
--- /dev/null
+++ b/time/bits/types/struct___timespec64.h
@@ -0,0 +1,39 @@
+/* NB: Include guard matches what <linux/time.h> uses.  */
+/* #ifndef _STRUCT_TIMESPEC
+# error "Never include <bits/types/struct___timespec64.h> directly !"
+#endif */
+
+#ifndef _STRUCT___TIMESPEC64
+#define _STRUCT___TIMESPEC64 1
+
+#include <bits/types.h>
+#include <bits/timesize.h>
+#include <endian.h>
+
+/* The glibc Y2038-proof structure for a time value.
+   To keep things Posix-ish, we keep the nanoseconds field a 32-bit
+   signed long, but since the Linux field is a 64-bit signed int, we
+   pad our tv_nsec with a 32-bit bitfield, which should always be 0.
+   */
+#if __TIMESIZE==64
+# define __timespec64 timespec
+#else
+#define TIMSPEC64_TV_PAD_DEFINED
+# 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
+#endif
+
+#endif
-- 
2.11.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]