[1/2] Y2038: add type __time64_t

Message ID 20180613070019.4639-2-albert.aribaud@3adev.fr
State New
Headers show
Series
  • Y2038 support batch 1 - __time64_t and __tz_convert
Related show

Commit Message

Albert ARIBAUD June 13, 2018, 7 a.m.
This type is public, so that time_t can be a typedef of it
when we switch the public API to 64-bit time.

Also, provide a function to check if a __time64_t value
fits in a (32-bit) __time_t.
---
 bits/typesizes.h                                 | 1 +
 include/time.h                                   | 9 ++++++++-
 posix/bits/types.h                               | 3 ++-
 sysdeps/mach/hurd/bits/typesizes.h               | 1 +
 sysdeps/unix/sysv/linux/alpha/bits/typesizes.h   | 1 +
 sysdeps/unix/sysv/linux/generic/bits/typesizes.h | 1 +
 sysdeps/unix/sysv/linux/s390/bits/typesizes.h    | 1 +
 sysdeps/unix/sysv/linux/sparc/bits/typesizes.h   | 1 +
 sysdeps/unix/sysv/linux/x86/bits/typesizes.h     | 1 +
 9 files changed, 17 insertions(+), 2 deletions(-)

Comments

Paul Eggert June 13, 2018, 8:38 a.m. | #1
Albert ARIBAUD (3ADEV) wrote:
> -__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
> +__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */

This change to commentary is confusing, as __time_t is Y2038-safe on 64-bit 
hosts. I suggest omitting the change, and changing the comment on the next line 
to "Seconds since the Epoch (TIME_BITS==64)" (or whatever the name of that macro 
is).
Albert ARIBAUD June 13, 2018, 12:36 p.m. | #2
Hi Paul,

On Wed, 13 Jun 2018 01:38:09 -0700, Paul Eggert <eggert@cs.ucla.edu>
wrote :

> Albert ARIBAUD (3ADEV) wrote:
> > -__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
> > +__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */  
> 
> This change to commentary is confusing, as __time_t is Y2038-safe on 64-bit 
> hosts. I suggest omitting the change, and changing the comment on the next line 
> to "Seconds since the Epoch (TIME_BITS==64)" (or whatever the name of that macro 
> is).

Fixed locally as suggested, will repost once 2/2 discussion is complete.

Cordialement,
Albert ARIBAUD
3ADEV
Joseph Myers June 13, 2018, 2:13 p.m. | #3
There is a key definition you are missing in this patch: one that says 
whether the particular glibc configuration supports 32-bit time_t at all.

This new macro could go in bits/wordsize.h, or in its own installed 
header.  The value is normally the same as (__WORDSIZE == 32), *except* on 
x32, which already has 64-bit time_t despite 32-bit wordsize.

The new macro would be used, in the installed headers, to control whether 
an explicit _TIME_BITS=32 is valid or not.  It would also be used, in 
glibc internals, to control whether there are separate 32-bit interfaces 
that wrap 64-bit ones, or whether the 64-bit names are just #defined to 
the generic ones (#define __clock_gettime64 __clock_gettime, in some 
internal header, for example) to avoid creating any new interfaces in the 
case where time_t is already 64-bit, while avoiding the need for lots of 
conditionals where glibc-internal code written for 64-bit time_t wishes to 
call such interfaces.
Albert ARIBAUD June 13, 2018, 4:19 p.m. | #4
Hi Joseph,

On Wed, 13 Jun 2018 14:13:00 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> There is a key definition you are missing in this patch: one that says 
> whether the particular glibc configuration supports 32-bit time_t at all.
> 
> This new macro could go in bits/wordsize.h, or in its own installed 
> header.  The value is normally the same as (__WORDSIZE == 32), *except* on 
> x32, which already has 64-bit time_t despite 32-bit wordsize.
> 
> The new macro would be used, in the installed headers, to control whether 
> an explicit _TIME_BITS=32 is valid or not.  It would also be used, in 
> glibc internals, to control whether there are separate 32-bit interfaces 
> that wrap 64-bit ones, or whether the 64-bit names are just #defined to 
> the generic ones (#define __clock_gettime64 __clock_gettime, in some 
> internal header, for example) to avoid creating any new interfaces in the 
> case where time_t is already 64-bit, while avoiding the need for lots of 
> conditionals where glibc-internal code written for 64-bit time_t wishes to 
> call such interfaces.

Which would be best:

- a "boolean" macro (e.g. __TIMESIZE32) defined as (__WORDSIZE == 32)
  except for x32 where it would be defined as 1, or

- a "size" macro (e.g. __TIMESIZE) defined equal to __WORDSIZE except
  for x32 where it would be defined as 64?

I have a slight preference for the "size" form.

Cordialement,
Albert ARIBAUD
3ADEV
Paul Eggert June 13, 2018, 4:35 p.m. | #5
Albert ARIBAUD wrote:
> - a "size" macro (e.g. __TIMESIZE) defined equal to __WORDSIZE except
>    for x32 where it would be defined as 64?
> 
> I have a slight preference for the "size" form.

Works for me. Though C11 uses _WIDTH for names that count bit widths of 
integers, so I'd mildly prefer __TIME_WIDTH as it is a new name.
Joseph Myers June 13, 2018, 4:39 p.m. | #6
On Wed, 13 Jun 2018, Paul Eggert wrote:

> Albert ARIBAUD wrote:
> > - a "size" macro (e.g. __TIMESIZE) defined equal to __WORDSIZE except
> >    for x32 where it would be defined as 64?
> > 
> > I have a slight preference for the "size" form.
> 
> Works for me. Though C11 uses _WIDTH for names that count bit widths of
> integers, so I'd mildly prefer __TIME_WIDTH as it is a new name.

Whatever the name, it needs to be clear that this macro relates to the 
time_t used by default (unsuffixed) functions in this glibc - *not* 
necessarily the time_t for the current compilation.  (Rather, _TIME_BITS 
== 64 && (new macro) == 32 would be the condition for the installed 
headers to need to redirect calls to time-related functions.)

The width macros are from TS 18661-1, not C11 (hopefully they'll end up as 
an unconditional feature of C2x without requiring 
__STDC_WANT_IEC_60559_BFP_EXT__, since there is demand for them outside 
the floating-point context of passing them to the fromfp functions).  If 
there were a TIME_WIDTH addition to that set of macros, I'd expect it to 
relate to the current compilation.
Paul Eggert June 13, 2018, 6:46 p.m. | #7
On 06/13/2018 09:39 AM, Joseph Myers wrote:
> Whatever the name, it needs to be clear that this macro relates to the
> time_t used by default (unsuffixed) functions in this glibc -*not*  
> necessarily the time_t for the current compilation.

OK, in that case perhaps it's better to stick to __TIMESIZE, as the 
_WIDTH names are intended to apply to the current compilation. (Sorry 
about confusing C11 with TS 18661-1.)

Patch

diff --git a/bits/typesizes.h b/bits/typesizes.h
index 85eacf2518..0b6a19c230 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -48,6 +48,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/include/time.h b/include/time.h
index 23d2580528..93638aa215 100644
--- a/include/time.h
+++ b/include/time.h
@@ -3,6 +3,7 @@ 
 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
+# include <stdbool.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -101,10 +102,16 @@  extern char * __strptime_internal (const char *rp, const char *fmt,
 
 extern double __difftime (time_t time1, time_t time0);
 
-
 /* Use in the clock_* functions.  Size of the field representing the
    actual clock ID.  */
 #define CLOCK_IDFIELD_SIZE	3
 
+/* check whether a time64_t value fits in a time_t */
+static inline bool
+fits_in_time_t (__time64_t t)
+{
+  return t == (time_t) t;
+}
+
 #endif
 #endif
diff --git a/posix/bits/types.h b/posix/bits/types.h
index 5e22ce41bf..4c6553a266 100644
--- a/posix/bits/types.h
+++ b/posix/bits/types.h
@@ -155,7 +155,8 @@  __STD_TYPE __CLOCK_T_TYPE __clock_t;	/* Type of CPU usage counts.  */
 __STD_TYPE __RLIM_T_TYPE __rlim_t;	/* Type for resource measurement.  */
 __STD_TYPE __RLIM64_T_TYPE __rlim64_t;	/* Type for resource measurement (LFS).  */
 __STD_TYPE __ID_T_TYPE __id_t;		/* General type for IDs.  */
-__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
+__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */
+__STD_TYPE __TIME64_T_TYPE __time64_t;	/* Seconds since the Epoch, Y2038-safe.  */
 __STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds.  */
 __STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds.  */
 
diff --git a/sysdeps/mach/hurd/bits/typesizes.h b/sysdeps/mach/hurd/bits/typesizes.h
index d3026ba66e..c9dbe2bf33 100644
--- a/sysdeps/mach/hurd/bits/typesizes.h
+++ b/sysdeps/mach/hurd/bits/typesizes.h
@@ -48,6 +48,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
index d9a0b0467c..47b1e36165 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h
@@ -47,6 +47,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__S64_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
index a2cb3433bf..db03b1ae8b 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
@@ -49,6 +49,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
index fdaa421958..138c6d6d10 100644
--- a/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/s390/bits/typesizes.h
@@ -48,6 +48,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
index b59f2ced75..5d6fb00a93 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h
@@ -48,6 +48,7 @@ 
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__S32_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
index e6f7481a19..f5d792d8f3 100644
--- a/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/typesizes.h
@@ -62,6 +62,7 @@ 
 #define __ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SYSCALL_SLONG_TYPE
 #define __TIME_T_TYPE		__SYSCALL_SLONG_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SYSCALL_SLONG_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE