Patchwork Y2038: provide kernel support indication

login
register
mail settings
Submitter Albert ARIBAUD
Date Sept. 19, 2018, 7:13 a.m.
Message ID <20180919071303.26636-1-albert.aribaud@3adev.fr>
Download mbox | patch
Permalink /patch/29457/
State New
Headers show

Comments

Albert ARIBAUD - Sept. 19, 2018, 7:13 a.m.
* New function __y2038_get_kernel_support() returns:
  * 0 if the underlying kernel does not support Y2038 at all
  * > 0 if the underlying kernel has some support for Y2038
  * < 0 if the underlying kernel support for Y2038 is broken
* New function __y2038_set_kernel_support() allows indicating
  a kernel's Y2038 support (or support failure)
* Default implementation (covering non-Linux kernels) always
  returns 0 (no support).
---

This patch is part of the Y2038 patch series, which is available at
<https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/aaribaud/y2038>.
Warning: this branch may be rebased on current master and/or updated based on
feedback from the list at any time.

 misc/Makefile                           |  2 +-
 misc/Versions                           |  4 +++
 misc/y2038-support.c                    | 32 ++++++++++++++++++++
 misc/y2038-support.h                    | 36 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/y2038-support.c | 40 +++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/y2038-support.h | 30 +++++++++++++++++++
 6 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 misc/y2038-support.c
 create mode 100644 misc/y2038-support.h
 create mode 100644 sysdeps/unix/sysv/linux/y2038-support.c
 create mode 100644 sysdeps/unix/sysv/linux/y2038-support.h
Joseph Myers - Sept. 19, 2018, 1:03 p.m.
On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:

> * New function __y2038_get_kernel_support() returns:
>   * 0 if the underlying kernel does not support Y2038 at all
>   * > 0 if the underlying kernel has some support for Y2038
>   * < 0 if the underlying kernel support for Y2038 is broken
> * New function __y2038_set_kernel_support() allows indicating
>   a kernel's Y2038 support (or support failure)
> * Default implementation (covering non-Linux kernels) always
>   returns 0 (no support).

There should be an __ASSUME_* macro that kernel-features.h defines when 
the minimum kernel version has the required feature.  Calls to these APIs 
need to become compile-time constants in that case, with the functions / 
variables not existing in the glibc binaries at all.

> +  GLIBC_2.29 {
> +    __y2038_get_kernel_support;
> +    __y2038_set_kernel_support;
> +  }

I don't think these should be public interfaces (but if they were, the 
patch would need to update all the ABI test baselines).  If exported for 
use by other glibc shared libraries, they should be exported at version 
GLIBC_PRIVATE.  (That does require they are never used in code in 
*_nonshared.a because that may end up in users' programs / shared 
libraries, but very little should go in *_nonshared.a.)
Paul Eggert - Sept. 19, 2018, 4:11 p.m.
Albert ARIBAUD (3ADEV) wrote:
> +/* Indicates Y2038 support.
> + * 0 means no suppport
> + * > 0 means (some) support
> + * < 0 means support is broken
> + * Can be read directly from within libc linux-related files.
> + * Can be written non-zero to indicate support or lack thereof.
> + */
> +extern int __y2038_linux_support;

This variable needs a better comment, since it's not clear from that comment 
what it's for. In the current branch, I don't see any code setting the variable 
to a positive value; it defaults to 0 and if any glibc code discovers anything 
that looks like a y2038 bug, the variable is set to -1.

So it looks like a cache: as glibc discovers y2038 bugs, it uses the cache to 
avoid trying to invoke system calls that it knows will fail anyway with ENOSYS, 
or something like that. If that's the intent, it needs to be documented in the 
variable.

However, I imagine that some kernels will have some y2038 bugs but not others. 
For example, clock_gettime and related functions might work fine on a particular 
kernel, but some ioctls might not work (or might work for some devices but not 
others) due to device-drivers not being y2038-safe. How is __y2038_linux_support 
supposed to reflect this more-complicated situation?
Albert ARIBAUD - Sept. 24, 2018, 9:34 p.m.
Hi Paul,

On Wed, 19 Sep 2018 09:11:18 -0700, Paul Eggert <eggert@cs.ucla.edu>
wrote :

> Albert ARIBAUD (3ADEV) wrote:
> > +/* Indicates Y2038 support.
> > + * 0 means no suppport
> > + * > 0 means (some) support
> > + * < 0 means support is broken
> > + * Can be read directly from within libc linux-related files.
> > + * Can be written non-zero to indicate support or lack thereof.
> > + */
> > +extern int __y2038_linux_support;  
> 
> This variable needs a better comment, since it's not clear from that comment 
> what it's for. In the current branch, I don't see any code setting the variable 
> to a positive value; it defaults to 0 and if any glibc code discovers anything 
> that looks like a y2038 bug, the variable is set to -1.
> 
> So it looks like a cache: as glibc discovers y2038 bugs, it uses the cache to 
> avoid trying to invoke system calls that it knows will fail anyway with ENOSYS, 
> or something like that. If that's the intent, it needs to be documented in the 
> variable.
>
> However, I imagine that some kernels will have some y2038 bugs but not others. 
> For example, clock_gettime and related functions might work fine on a particular 
> kernel, but some ioctls might not work (or might work for some devices but not 
> others) due to device-drivers not being y2038-safe. How is __y2038_linux_support 
> supposed to reflect this more-complicated situation?

Right now we can use the bits in __y2038_linux_support to indicate
level of support (when positive) or reasons for not supporting (when
negative). That's 31 distinct flags.

If we want to be able to use more than 31 bits, we could reuse the
bitset_t type of the posix/regex_internal.h file and make the variable
a bitset_t. Then we could define an arbitrary number of Y2038 features /
quirks / bugs as bit indices:

  /* Y2038 unique feature/quirk/bug identifiers.  */

  /* Kernel does or does not support Y2038 globally.  */
  #define Y2038_FEATURE 0

  /* Linux kernel does or does not provide clock_gettime64 syscall.  */
  #define Y2038_FEATURE_LINUX_CLOCK_GETTIME64 1

  /* Linux kernel does or does not provide clock_settime64 syscall.  */
  #define Y2038_FEATURE_LINUX_CLOCK_SETTIME64 2
  /* etc.  *.

  [...]

  /* Linux kernel clock_gettime64 implementation has quirk 'XYZ'
  #define Y2038_FEATURE_LINUX_CLOCK_GETTIME64_XYZ 42
  /* etc.  */

(there could be a set of indices for Linux, another for BSD, etc.)

For glibc modules which could not directly access the variable (and
thus could not use the inline bitset_t functions, we would provide
getters and setters named after their bitset_t equivalents:

  bool __y2038_kernel_feature_contain(int feature);
  bool __y2038_kernel_feature_set(int feature);
  bool __y2038_kernel_feature_clear(int feature);

Comments?

Cordialement,
Albert ARIBAUD
3ADEV
Paul Eggert - Sept. 24, 2018, 9:50 p.m.
On 9/24/18 2:34 PM, Albert ARIBAUD wrote:
> Right now we can use the bits in __y2038_linux_support to indicate
> level of support (when positive) or reasons for not supporting (when
> negative). That's 31 distinct flags.

Rather than trying to shoehorn this into a single central integer or 
bitset that governs everything that could go wrong or right with Y2038, 
how about having a separate boolean (or whatever) variable for each 
feature? That way, only code that is worried about that feature needs to 
know about the variable, and it's easier to add or remove variables as 
the need for them is discovered or abandoned.

>    /* Linux kernel does or does not provide clock_gettime64 syscall.  */
>    #define Y2038_FEATURE_LINUX_CLOCK_GETTIME64 1
>
>    /* Linux kernel does or does not provide clock_settime64 syscall.  */
>    #define Y2038_FEATURE_LINUX_CLOCK_SETTIME64 2

Will there ever be a kernel that provides one syscall but not the other? 
We shouldn't need variables for each theoretically-possible platform, 
only for the platforms that exist, or are likely to.
Albert ARIBAUD - Sept. 24, 2018, 9:56 p.m.
Hi Joseph,

On Wed, 19 Sep 2018 13:03:21 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:
> 
> > * New function __y2038_get_kernel_support() returns:
> >   * 0 if the underlying kernel does not support Y2038 at all
> >   * > 0 if the underlying kernel has some support for Y2038
> >   * < 0 if the underlying kernel support for Y2038 is broken
> > * New function __y2038_set_kernel_support() allows indicating
> >   a kernel's Y2038 support (or support failure)
> > * Default implementation (covering non-Linux kernels) always
> >   returns 0 (no support).  
> 
> There should be an __ASSUME_* macro that kernel-features.h defines when 
> the minimum kernel version has the required feature.  Calls to these APIs 
> need to become compile-time constants in that case, with the functions / 
> variables not existing in the glibc binaries at all.

Ok, how about __ASSUME_KERNEL_Y2038_SUPPORT?

In case it is not defined, then all Y2038 feature support calls would
return 'no support'.

Considering right now no kernel has 64-bit-time syscalls (there is only
a patch series / development branch which provides some for some
architectures), __ASSUME_KERNEL_Y2038_SUPPORT should remain undefined
(but I will define it for testing with the dev branch).

So what is the best option:

- not define it at all (at the risk of people wondering why I am
  referring to an undefined __ASSUME_*)

- Just #undef it in sysdeps/unix/sysv/linux/kernel-features.h even
  though it is not #define'd elsewhere?

- #define it in sysdeps/unix/sysv/linux/kernel-features.h and then
  #undef it in sysdeps/unix/sysv/linux/*/kernel-features.h, and later
  when some architecture gets Y2038 syscall support, remove its #undef?

> > +  GLIBC_2.29 {
> > +    __y2038_get_kernel_support;
> > +    __y2038_set_kernel_support;
> > +  }  
> 
> I don't think these should be public interfaces (but if they were, the 
> patch would need to update all the ABI test baselines).  If exported for 
> use by other glibc shared libraries, they should be exported at version 
> GLIBC_PRIVATE.  (That does require they are never used in code in 
> *_nonshared.a because that may end up in users' programs / shared 
> libraries, but very little should go in *_nonshared.a.)

Indeed, some glibc shared libs will need those, but there is little
reason that public code should use them. I will switch to GLIBC_PRIVATE
(but the names and number of functions will probably change, see Paul's
comments re Y2038 features).

Cordialement,
Albert ARIBAUD
3ADEV
Albert ARIBAUD - Sept. 24, 2018, 10:11 p.m.
Hi Paul,

Le Mon, 24 Sep 2018 14:50:34 -0700, Paul Eggert <eggert@cs.ucla.edu> a
écrit :

> On 9/24/18 2:34 PM, Albert ARIBAUD wrote:
> > Right now we can use the bits in __y2038_linux_support to indicate
> > level of support (when positive) or reasons for not supporting (when
> > negative). That's 31 distinct flags.  
> 
> Rather than trying to shoehorn this into a single central integer or 
> bitset that governs everything that could go wrong or right with Y2038, 
> how about having a separate boolean (or whatever) variable for each 
> feature? That way, only code that is worried about that feature needs to 
> know about the variable, and it's easier to add or remove variables as 
> the need for them is discovered or abandoned.

How would each 'feature' be defined? For instance, right now, either
the Linux kernel has no Y2038-proof syscalls at all, or it has a known
list of them (added in the kernel Y2038 syscall branch). Would that be
one 'feature', on the grounds that later kernels will provide at least
the same set, and possible a larget set, of Y2038 syscalls? Or as many
features as there are syscalls, on the grounds that some of these
syscalls may one day disappear?

> >    /* Linux kernel does or does not provide clock_gettime64 syscall.  */
> >    #define Y2038_FEATURE_LINUX_CLOCK_GETTIME64 1
> >
> >    /* Linux kernel does or does not provide clock_settime64 syscall.  */
> >    #define Y2038_FEATURE_LINUX_CLOCK_SETTIME64 2  
> 
> Will there ever be a kernel that provides one syscall but not the other? 
> We shouldn't need variables for each theoretically-possible platform, 
> only for the platforms that exist, or are likely to.

Those were examples only. Right now, apart from a general "architecture
now has support for Y2038 syscalls" feature, the only feature I can see
will happen is "syscall X has quirk Y  [for architecture Z]". What
other sort of feature should we expect?

Cordialement,
Albert ARIBAUD
3ADEV
Paul Eggert - Sept. 25, 2018, 6:19 a.m.
Albert ARIBAUD wrote:
> How would each 'feature' be defined? For instance, right now, either
> the Linux kernel has no Y2038-proof syscalls at all, or it has a known
> list of them (added in the kernel Y2038 syscall branch). Would that be
> one 'feature', on the grounds that later kernels will provide at least
> the same set, and possible a larget set, of Y2038 syscalls? Or as many
> features as there are syscalls, on the grounds that some of these
> syscalls may one day disappear?

The former sounds better, at least for now. It can evolve to the latter if and 
when the syscall set mutates. I see little advantage to starting with the latter 
now.


> Right now, apart from a general "architecture
> now has support for Y2038 syscalls" feature, the only feature I can see
> will happen is "syscall X has quirk Y  [for architecture Z]".

Yes, that's the sort of thing that I expect too. But unless I'm missing 
something, we don't have a strong need for a central repository that catalogs 
these quirks, as they're likely to be local to single modules[
Albert ARIBAUD - Sept. 25, 2018, 9:13 a.m.
Hi Paul,

On Mon, 24 Sep 2018 23:19:56 -0700, Paul Eggert <eggert@cs.ucla.edu>
wrote :

> Albert ARIBAUD wrote:
> > How would each 'feature' be defined? For instance, right now, either
> > the Linux kernel has no Y2038-proof syscalls at all, or it has a known
> > list of them (added in the kernel Y2038 syscall branch). Would that be
> > one 'feature', on the grounds that later kernels will provide at least
> > the same set, and possible a larget set, of Y2038 syscalls? Or as many
> > features as there are syscalls, on the grounds that some of these
> > syscalls may one day disappear?  
> 
> The former sounds better, at least for now. It can evolve to the latter if and 
> when the syscall set mutates. I see little advantage to starting with the latter 
> now.
> 
> 
> > Right now, apart from a general "architecture
> > now has support for Y2038 syscalls" feature, the only feature I can see
> > will happen is "syscall X has quirk Y  [for architecture Z]".  
> 
> Yes, that's the sort of thing that I expect too. But unless I'm missing 
> something, we don't have a strong need for a central repository that catalogs 
> these quirks, as they're likely to be local to single modules[

Ok, so:

- one new boolean for every new feature, which libc can read/write.
  Reading happens every time the feature is used.
  Writing happens very rarely, once when first first using / testing for
  the feature (e.g. at application start), once if using the feature
  fails (e.g. a syscall returns ENOSYS).

- two accessors (getter/setter) for every new feature if it must be
  read/set from another glibc library than libc (e.g. librt).

Cordialement,
Albert ARIBAUD
3ADEV
Florian Weimer - Sept. 25, 2018, 10:58 a.m.
* Albert ARIBAUD:

> - one new boolean for every new feature, which libc can read/write.
>   Reading happens every time the feature is used.
>   Writing happens very rarely, once when first first using / testing for
>   the feature (e.g. at application start), once if using the feature
>   fails (e.g. a syscall returns ENOSYS).
>
> - two accessors (getter/setter) for every new feature if it must be
>   read/set from another glibc library than libc (e.g. librt).

I'm still surprised that this is needed.  Why can't applications call
the function in question and react to a well-documented error code?

Thanks,
Florian
Albert ARIBAUD - Sept. 25, 2018, 4:47 p.m.
Hi Florian,

On Tue, 25 Sep 2018 12:58:25 +0200, Florian Weimer <fweimer@redhat.com>
wrote :

> * Albert ARIBAUD:
> 
> > - one new boolean for every new feature, which libc can read/write.
> >   Reading happens every time the feature is used.
> >   Writing happens very rarely, once when first first using / testing for
> >   the feature (e.g. at application start), once if using the feature
> >   fails (e.g. a syscall returns ENOSYS).
> >
> > - two accessors (getter/setter) for every new feature if it must be
> >   read/set from another glibc library than libc (e.g. librt).  
> 
> I'm still surprised that this is needed.  Why can't applications call
> the function in question and react to a well-documented error code?

These features are for glibc rather than for applications; they are
here for glibc to remember whether a Y2038 feature is available in the
kernel over which it currently runs.

Implementations for 64-bit time interfaces which rely on syscalls need
to be able to fall back to 32-bit-time syscalls if 64-bit-time syscalls
fail. Once a 64-bit-syscall has failed, it makes little sense to try it
again later; glibc can save the effort and directly call the 32-bit
syscall.

Applications, on the other hand, would call the 64-bit-time interface
regardless of the feature state. Whether this call would translate
into 64-bit-time or 32-bit-time syscalls would be invisible to them. 

> Thanks,
> Florian

Cordialement,
Albert ARIBAUD
3ADEV
Joseph Myers - Sept. 25, 2018, 5:25 p.m.
On Mon, 24 Sep 2018, Albert ARIBAUD wrote:

> > There should be an __ASSUME_* macro that kernel-features.h defines when 
> > the minimum kernel version has the required feature.  Calls to these APIs 
> > need to become compile-time constants in that case, with the functions / 
> > variables not existing in the glibc binaries at all.
> 
> Ok, how about __ASSUME_KERNEL_Y2038_SUPPORT?
> 
> In case it is not defined, then all Y2038 feature support calls would
> return 'no support'.

Well, normally "not defined" for __ASSUME_* doesn't mean "no support"; it 
means "support may or may not be present, and needs to be tested for at 
runtime if the __NR_* macros in question are defined".

Before we work out what the macro (or macros if more than one is needed) 
is called, and the semantics of it being defined or undefined, we need to 
have a clear understanding of the semantics.  And that in turn requires a 
clear understanding of what the future kernel interfaces will be.

Could you provide a description of what the kernel interfaces will be in 
future for each of the following cases (and any other significantly 
different variants I've missed)?  Then, indicate whether you'd expect the 
__ASSUME_* macro or macros to be defined in each of those cases.  
Hopefully this will help clarify what the interfaces should look like 
within glibc.  (This information will also need to go in the proposed 
glibc commit messages for future versions of the present patch, and quite 
likely some of it should go in comments in glibc code.)


1a. Existing 64-bit architectures, where 64-bit time_t is the only variant 
supported, in both the kernel and (if those architectures already have 
glibc ports) glibc.

My expectation is that these will *not* provide any new syscalls and will 
*not* provide any new __NR_* aliases for existing syscalls.  Is that 
correct?

If so, would the __ASSUME_* macro be defined for those architectures or 
not?  Whether it is or not, there must *not* be any new variables or 
internal functions defined in glibc at all relating to Y2038 support, or 
any additional levels of function calls / wrappers at runtime when 
time-related glibc functions are used, given that there are no Y2038 
problems for those architectures at present anyway.  (Avoiding such extra 
code and data might involve e.g. __TIMESIZE conditionals.  Naturally it's 
*also* desirable to design the implementation internals to reduce the 
number of places needing such conditionals.)


1b. New 64-bit architectures (not currently supported in the kernel).

My expectation is that these will be the same as old ones - they will 
provide the existing syscalls (minus obsolete ones), under their existing 
names, not any new ones that explicitly reference 64-bit time.  Is that 
correct?  If so, I'd expect them to look exactly like case 1a in glibc.


2a. Existing 32-bit architectures, supported in both the kernel and glibc 
with 32-bit time_t.

These will all need to gain new syscalls under new names, with the new 
macro defined when those syscalls are known to be available at runtime.


2b. Existing 32-bit architectures, already supported in the kernel, but 
not supported in glibc until after the 64-bit time support is present in 
both places.

From the point of view of the kernel, these should be exactly like case 
2a.  But from the point of view of glibc, they might be different - we 
might want to support only 64-bit time for them (so __TIMESIZE would be 
64, and _TIME_BITS=64 would do nothing).  Is that what you'd intend for 
such new architectures in glibc?  If so, presumably the __ASSUME_* macro 
would still be defined for them, but the combination of that macro and 
__TIMESIZE == 64 might end up doing different things in some places?  And 
would the glibc port for such an architecture allow runtime fallback to 
32-bit time syscalls, or would it also require a minimum kernel with 
64-bit time support rather than allowing older kernels from before the 
glibc port was added?

(Of course you can't really test this combination; it may fall to whoever 
adds the first such architecture port to glibc to get it working.)

Another consideration for such architectures is whether you end up with 
the combination of 64-bit time and 32-bit file offsets for them (given 
_TIME_BITS=64 requires _FILE_OFFSET_BITS=64, but here you have 64-bit time 
without defining _TIME_BITS).  It might make sense for such architectures 
also to use 64-bit offsets unconditionally, like 64-bit architectures do, 
so that defining _FILE_OFFSET_BITS=64 for them only affects mangling for a 
few types, not layout.


3. New 32-bit architectures (new in both kernel and glibc after the 
addition of 64-bit time support for 32-bit architectures in the kernel).

My expectation is that these will *only* have the new-named syscalls for 
64-bit time, not the old-named syscalls that use 32-bit time on 32-bit 
systems (and not the old syscall names but pointing to syscalls that use 
64-bit time, either).  Is that correct - new-named syscalls only for 
everything involving time on such architectures?

Then I'd expect those to look much like case 2b within glibc, except that 
arch_minimum_kernel would be recent enough that any code that might 
attempt to fall back to 32-bit-time syscalls would be compiled out.

> - Just #undef it in sysdeps/unix/sysv/linux/kernel-features.h even
>   though it is not #define'd elsewhere?

I think this, or a commented-out definition with the comment explaining 
the intended semantics.

> - #define it in sysdeps/unix/sysv/linux/kernel-features.h and then
>   #undef it in sysdeps/unix/sysv/linux/*/kernel-features.h, and later
>   when some architecture gets Y2038 syscall support, remove its #undef?

I'd hope all 32-bit architectures get kernel support at the same time.  
Is that the intent, or is something else intended?

If 64-bit architectures should have the macro undefined, then 
sysdeps/unix/sysv/linux/kernel-features.h will need to have a conditional 
deciding whether to undefine it, based on "is this an architecture for 
which the ordinary time syscalls always use 64-bit time_t?".  That 
conditional is *not* quite __WORDSIZE == 64, in that such a conditional 
would be wrong for x32, but it's also not __TIMESIZE == 64, if the answer 
for cases 2b and 3 above is that they would have __TIMESIZE == 64.  
Supposing that is indeed the case for cases 2b and 3, it would seem 
reasonable to use __WORDSIZE == 64 in the generic kernel-features.h and 
then override it in x86_64/kernel-features.h.  What we *don't* want is a 
situation where all future 32-bit architectures need to have their own 
overrides - the default case for future architectures must be not needing 
their own kernel-features.h file at all.
Albert ARIBAUD - Sept. 25, 2018, 7:36 p.m.
Hi Joseph,

CC:ing Arnd re whether all 32-bit architectures will get 64-bit-time
kernel support.

On Tue, 25 Sep 2018 17:25:39 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Mon, 24 Sep 2018, Albert ARIBAUD wrote:
> 
> > > There should be an __ASSUME_* macro that kernel-features.h defines when 
> > > the minimum kernel version has the required feature.  Calls to these APIs 
> > > need to become compile-time constants in that case, with the functions / 
> > > variables not existing in the glibc binaries at all.  
> > 
> > Ok, how about __ASSUME_KERNEL_Y2038_SUPPORT?
> > 
> > In case it is not defined, then all Y2038 feature support calls would
> > return 'no support'.  
> 
> Well, normally "not defined" for __ASSUME_* doesn't mean "no support"; it 
> means "support may or may not be present, and needs to be tested for at 
> runtime if the __NR_* macros in question are defined".

So, assuming V is the version at which 64-bit-time kernel support is
introduced for all architectures at the same time:

- if the minimal kernel version supported by glibc for a given
  architecture is less than V, then __ASSUME_KERNEL_Y2038_SUPPORT should
  be undefined and glibc should check dynamically whether the actual
  kernel it is running on has 64-bit-time support or not;

- if the minimal kernel version supported by glibc for a given
  architecture is V or greater, then __ASSUME_KERNEL_Y2038_SUPPORT
  should be defined and glibc checks for support should be turned
  into constants so that 64-bit-time syscalls are systematically
  called.

Correct?

> Before we work out what the macro (or macros if more than one is needed) 
> is called, and the semantics of it being defined or undefined, we need to 
> have a clear understanding of the semantics.  And that in turn requires a 
> clear understanding of what the future kernel interfaces will be.
> 
> Could you provide a description of what the kernel interfaces will be in 
> future for each of the following cases (and any other significantly 
> different variants I've missed)?  Then, indicate whether you'd expect the 
> __ASSUME_* macro or macros to be defined in each of those cases.  
> Hopefully this will help clarify what the interfaces should look like 
> within glibc.  (This information will also need to go in the proposed 
> glibc commit messages for future versions of the present patch, and quite 
> likely some of it should go in comments in glibc code.)
> 
> 
> 1a. Existing 64-bit architectures, where 64-bit time_t is the only variant 
> supported, in both the kernel and (if those architectures already have 
> glibc ports) glibc.
> 
> My expectation is that these will *not* provide any new syscalls and will 
> *not* provide any new __NR_* aliases for existing syscalls.  Is that 
> correct?

Yes, that is correct.

> If so, would the __ASSUME_* macro be defined for those architectures or 
> not?  Whether it is or not, there must *not* be any new variables or 
> internal functions defined in glibc at all relating to Y2038 support, or 
> any additional levels of function calls / wrappers at runtime when 
> time-related glibc functions are used, given that there are no Y2038 
> problems for those architectures at present anyway.  (Avoiding such extra 
> code and data might involve e.g. __TIMESIZE conditionals.  Naturally it's 
> *also* desirable to design the implementation internals to reduce the 
> number of places needing such conditionals.)
> 
> 
> 1b. New 64-bit architectures (not currently supported in the kernel).
> 
> My expectation is that these will be the same as old ones - they will 
> provide the existing syscalls (minus obsolete ones), under their existing 
> names, not any new ones that explicitly reference 64-bit time.  Is that 
> correct?  If so, I'd expect them to look exactly like case 1a in glibc.

I think this is correct.

> 2a. Existing 32-bit architectures, supported in both the kernel and glibc 
> with 32-bit time_t.
> 
> These will all need to gain new syscalls under new names, with the new 
> macro defined when those syscalls are known to be available at runtime.

Correct.

> 2b. Existing 32-bit architectures, already supported in the kernel, but 
> not supported in glibc until after the 64-bit time support is present in 
> both places.
> 
> >From the point of view of the kernel, these should be exactly like case   
> 2a.  But from the point of view of glibc, they might be different - we 
> might want to support only 64-bit time for them (so __TIMESIZE would be 
> 64, and _TIME_BITS=64 would do nothing).  Is that what you'd intend for 
> such new architectures in glibc?  If so, presumably the __ASSUME_* macro 
> would still be defined for them, but the combination of that macro and 
> __TIMESIZE == 64 might end up doing different things in some places?  And 
> would the glibc port for such an architecture allow runtime fallback to 
> 32-bit time syscalls, or would it also require a minimum kernel with 
> 64-bit time support rather than allowing older kernels from before the 
> glibc port was added?
> 
> (Of course you can't really test this combination; it may fall to whoever 
> adds the first such architecture port to glibc to get it working.)
> 
> Another consideration for such architectures is whether you end up with 
> the combination of 64-bit time and 32-bit file offsets for them (given 
> _TIME_BITS=64 requires _FILE_OFFSET_BITS=64, but here you have 64-bit time 
> without defining _TIME_BITS).  It might make sense for such architectures 
> also to use 64-bit offsets unconditionally, like 64-bit architectures do, 
> so that defining _FILE_OFFSET_BITS=64 for them only affects mangling for a 
> few types, not layout.

As you point out, I won't test for this combination, but yes, my
opinion is that 32-bit architectures which are supported in the kernel
but not yet in glibc should only use 64-bit time syscalls when glibc
support is added.

> 3. New 32-bit architectures (new in both kernel and glibc after the 
> addition of 64-bit time support for 32-bit architectures in the kernel).
> 
> My expectation is that these will *only* have the new-named syscalls for 
> 64-bit time, not the old-named syscalls that use 32-bit time on 32-bit 
> systems (and not the old syscall names but pointing to syscalls that use 
> 64-bit time, either).  Is that correct - new-named syscalls only for 
> everything involving time on such architectures?

I think this is correct.

> Then I'd expect those to look much like case 2b within glibc, except that 
> arch_minimum_kernel would be recent enough that any code that might 
> attempt to fall back to 32-bit-time syscalls would be compiled out.
> 
> > - Just #undef it in sysdeps/unix/sysv/linux/kernel-features.h even
> >   though it is not #define'd elsewhere?  
> 
> I think this, or a commented-out definition with the comment explaining 
> the intended semantics.

Ok.

> > - #define it in sysdeps/unix/sysv/linux/kernel-features.h and then
> >   #undef it in sysdeps/unix/sysv/linux/*/kernel-features.h, and later
> >   when some architecture gets Y2038 syscall support, remove its #undef?  
> 
> I'd hope all 32-bit architectures get kernel support at the same time.  
> Is that the intent, or is something else intended?

Arnd would know this much better than I do.

> If 64-bit architectures should have the macro undefined, then 
> sysdeps/unix/sysv/linux/kernel-features.h will need to have a conditional 
> deciding whether to undefine it, based on "is this an architecture for 
> which the ordinary time syscalls always use 64-bit time_t?".  That 
> conditional is *not* quite __WORDSIZE == 64, in that such a conditional 
> would be wrong for x32, but it's also not __TIMESIZE == 64, if the answer 
> for cases 2b and 3 above is that they would have __TIMESIZE == 64.  
> Supposing that is indeed the case for cases 2b and 3, it would seem 
> reasonable to use __WORDSIZE == 64 in the generic kernel-features.h and 
> then override it in x86_64/kernel-features.h.  What we *don't* want is a 
> situation where all future 32-bit architectures need to have their own 
> overrides - the default case for future architectures must be not needing 
> their own kernel-features.h file at all.

Cordialement,
Albert ARIBAUD
3ADEV
arnd@arndb.de - Sept. 25, 2018, 8:14 p.m.
On Tue, Sep 25, 2018 at 9:36 PM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote:
>
> CC:ing Arnd re whether all 32-bit architectures will get 64-bit-time
> kernel support.
>
> On Tue, 25 Sep 2018 17:25:39 +0000, Joseph Myers
> <joseph@codesourcery.com> wrote :
> > On Mon, 24 Sep 2018, Albert ARIBAUD wrote:
> > Before we work out what the macro (or macros if more than one is needed)
> > is called, and the semantics of it being defined or undefined, we need to
> > have a clear understanding of the semantics.  And that in turn requires a
> > clear understanding of what the future kernel interfaces will be.
> >
> > Could you provide a description of what the kernel interfaces will be in
> > future for each of the following cases (and any other significantly
> > different variants I've missed)?  Then, indicate whether you'd expect the
> > __ASSUME_* macro or macros to be defined in each of those cases.
> > Hopefully this will help clarify what the interfaces should look like
> > within glibc.  (This information will also need to go in the proposed
> > glibc commit messages for future versions of the present patch, and quite
> > likely some of it should go in comments in glibc code.)
> >
> >
> > 1a. Existing 64-bit architectures, where 64-bit time_t is the only variant
> > supported, in both the kernel and (if those architectures already have
> > glibc ports) glibc.
> >
> > My expectation is that these will *not* provide any new syscalls and will
> > *not* provide any new __NR_* aliases for existing syscalls.  Is that
> > correct?
>
> Yes, that is correct.

I was undecided on this issue actually: it does make some sense to
me to have the syscall macros be the same in the long run, so that
glibc doesn't have to pick between __NR_clock_gettime and
__NR_clock_gettime64 in a few years, after all supported kernels
support __NR_clock_gettime64. Also, 64-bit architectures won't
reuse the number space that we reserve for the new calls on 32-bit
architectures, so the addition is essentially free.

OTOH, it does seem a bit silly to have two syscall numbers that
point to the same symbol.

I don't have a strong preference here, and can do whichever
you like better in glibc.

> > If so, would the __ASSUME_* macro be defined for those architectures or
> > not?  Whether it is or not, there must *not* be any new variables or
> > internal functions defined in glibc at all relating to Y2038 support, or
> > any additional levels of function calls / wrappers at runtime when
> > time-related glibc functions are used, given that there are no Y2038
> > problems for those architectures at present anyway.  (Avoiding such extra
> > code and data might involve e.g. __TIMESIZE conditionals.  Naturally it's
> > *also* desirable to design the implementation internals to reduce the
> > number of places needing such conditionals.)
> >
> >
> > 1b. New 64-bit architectures (not currently supported in the kernel).
> >
> > My expectation is that these will be the same as old ones - they will
> > provide the existing syscalls (minus obsolete ones), under their existing
> > names, not any new ones that explicitly reference 64-bit time.  Is that
> > correct?  If so, I'd expect them to look exactly like case 1a in glibc.
>
> I think this is correct.

See above.

> > 2a. Existing 32-bit architectures, supported in both the kernel and glibc
> > with 32-bit time_t.
> >
> > These will all need to gain new syscalls under new names, with the new
> > macro defined when those syscalls are known to be available at runtime.
>
> Correct.

Right.

> > 2b. Existing 32-bit architectures, already supported in the kernel, but
> > not supported in glibc until after the 64-bit time support is present in
> > both places.
> >
> > >From the point of view of the kernel, these should be exactly like case
> > 2a.  But from the point of view of glibc, they might be different - we
> > might want to support only 64-bit time for them (so __TIMESIZE would be
> > 64, and _TIME_BITS=64 would do nothing).  Is that what you'd intend for
> > such new architectures in glibc?  If so, presumably the __ASSUME_* macro
> > would still be defined for them, but the combination of that macro and
> > __TIMESIZE == 64 might end up doing different things in some places?  And
> > would the glibc port for such an architecture allow runtime fallback to
> > 32-bit time syscalls, or would it also require a minimum kernel with
> > 64-bit time support rather than allowing older kernels from before the
> > glibc port was added?
> >
> > (Of course you can't really test this combination; it may fall to whoever
> > adds the first such architecture port to glibc to get it working.)
> >
> > Another consideration for such architectures is whether you end up with
> > the combination of 64-bit time and 32-bit file offsets for them (given
> > _TIME_BITS=64 requires _FILE_OFFSET_BITS=64, but here you have 64-bit time
> > without defining _TIME_BITS).  It might make sense for such architectures
> > also to use 64-bit offsets unconditionally, like 64-bit architectures do,
> > so that defining _FILE_OFFSET_BITS=64 for them only affects mangling for a
> > few types, not layout.
>
> As you point out, I won't test for this combination, but yes, my
> opinion is that 32-bit architectures which are supported in the kernel
> but not yet in glibc should only use 64-bit time syscalls when glibc
> support is added.

riscv32 falls into this category: there is preliminary kernel support
for it, but no upstream glibc. The riscv maintainers have indicated a
preference that they would actually want to drop the 32-bit time_t
syscalls from the kernel as well, since nobody is relying on them
today. I don't think it makes a difference to glibc, so we'll discuss this
among the kernel folks.

In general, we don't break established user ABIs as a rule, but we
also have lots of precedent for changing interfaces when we are
sure that there are no users that would complain about the change.

> > 3. New 32-bit architectures (new in both kernel and glibc after the
> > addition of 64-bit time support for 32-bit architectures in the kernel).
> >
> > My expectation is that these will *only* have the new-named syscalls for
> > 64-bit time, not the old-named syscalls that use 32-bit time on 32-bit
> > systems (and not the old syscall names but pointing to syscalls that use
> > 64-bit time, either).  Is that correct - new-named syscalls only for
> > everything involving time on such architectures?
>
> I think this is correct.

Yes, absolutely. Both csky and mips p32 will possibly fall into this
category, but it depends on how soon we can complete the addition
of the 64-bit time_t syscalls.

> > > - #define it in sysdeps/unix/sysv/linux/kernel-features.h and then
> > >   #undef it in sysdeps/unix/sysv/linux/*/kernel-features.h, and later
> > >   when some architecture gets Y2038 syscall support, remove its #undef?
> >
> > I'd hope all 32-bit architectures get kernel support at the same time.
> > Is that the intent, or is something else intended?
>
> Arnd would know this much better than I do.

I have planned to do it that way in the past, but with csky, mips-p32
and rv32 eager to change over as fast as they can, it seems more
likely now that there will be two steps here:

a) some architectures that only support 64-bit time_t from the start,
     possibly in linux-4.21
b) all other architectures supporting 64-bit time_t a little later, possibly
    4.22. This depends on work by Firoz Khan that is still under discussion
    at the moment.

There are also still a few open questions that we would need to resolve
in order to close in on the final ABI:

- The timex  structure for clock_adjtime64. I'd like to use the
   same version that x32 uses today, so we can avoid creating another
   32-bit compat interface for it. If there are any concerns with that,
   please let me know. In glibc, we will then have to change the
   __syscall_slong_t members of timex to a new type that is the
   same length as time_t.

- Whether to update itimerval (setitimer/getitimer) and rusage
  (getrusage, wait4, __kerrnel_waitid) or not. These only carry
  relative times, and they are in an awkward format (timeval).
  If we were to replace them, we'd probably want to use timespec
  on the syscall ABI, but that in turn means that glibc still
  requires a translation between the kernel structure and its
  own POSIX compatible structure. I'd appreciate to hear any
  opinions on this matter, one way or another, or alternative ideas.

- Whether to harmonize the existing syscall tables across all
  architectures while adding the new calls: I think this would be
  a good time to ensure that all architectures support all syscalls
  we have added over time, or at least define the number.
  This includes missing recent additions (io_pgetevents, rseq,
  fsinfo, ...) and those that may only exist as wrappers (ipc,
  socketcall) instead of direct entry points.

- In case we do harmonize the syscall tables, whether to go as
  far as using the same numbers for all of the new calls across
  the traditional architectures. E.g. clock_gettime64 could
  become 400 on x86, sparc, ppc, mips, ia64, etc and be
  followed by other 20 new calls with identical numbers.
  For the generic syscall ABI (arm64, openrisc, riscv, arc, ...)
  we'd probably use lower numbers to avoid a big gap, but at
  least that makes it only two possible numbers instead of 12
  for each call.

       Arnd
Joseph Myers - Sept. 25, 2018, 8:16 p.m.
On Tue, 25 Sep 2018, Albert ARIBAUD wrote:

> So, assuming V is the version at which 64-bit-time kernel support is
> introduced for all architectures at the same time:
> 
> - if the minimal kernel version supported by glibc for a given
>   architecture is less than V, then __ASSUME_KERNEL_Y2038_SUPPORT should
>   be undefined and glibc should check dynamically whether the actual
>   kernel it is running on has 64-bit-time support or not;
> 
> - if the minimal kernel version supported by glibc for a given
>   architecture is V or greater, then __ASSUME_KERNEL_Y2038_SUPPORT
>   should be defined and glibc checks for support should be turned
>   into constants so that 64-bit-time syscalls are systematically
>   called.
> 
> Correct?

Yes, subject to the question of what's appropriate on 64-bit architectures 
where time_t always has been 64-bit and the existing names of syscalls, 
not the new ones, are used for all time-related syscalls.  If 
__ASSUME_KERNEL_Y2038_SUPPORT means the syscalls with the new names are 
guaranteed to be present, then it should be undefined in that case because 
only the old names will be present (but also the variable etc. relating to 
runtime tests for support should not be declared at all, so if any code 
with such tests is - wrongly - compiled on such an architecture, it will 
fail to compile).
Joseph Myers - Sept. 25, 2018, 8:25 p.m.
On Tue, 25 Sep 2018, Joseph Myers wrote:

> Yes, subject to the question of what's appropriate on 64-bit architectures 
> where time_t always has been 64-bit and the existing names of syscalls, 
> not the new ones, are used for all time-related syscalls.  If 
> __ASSUME_KERNEL_Y2038_SUPPORT means the syscalls with the new names are 
> guaranteed to be present, then it should be undefined in that case because 
> only the old names will be present (but also the variable etc. relating to 
> runtime tests for support should not be declared at all, so if any code 
> with such tests is - wrongly - compiled on such an architecture, it will 
> fail to compile).

There is of course also a possible variant for 64-bit architectures if it 
proves better for the implementation:

* Make a glibc-internal header #define all the __NR_* for the new syscall 
names to point to the old names if the kernel headers don't do so.

* Define __ASSUME_KERNEL_Y2038_SUPPORT unconditionally for such 
architectures, because the syscalls in question are in fact old ones so 
always present at runtime.  (If the kernel headers might define the new 
__NR_* names *and point them to new syscall numbers*, it's more 
complicated, because in that case it would no longer be correct to assume 
the syscalls are available with an old kernel, but it would be completely 
useless to have runtime checks to decide between using old and new syscall 
numbers for the same syscall.  Also, if there are new syscalls that e.g. 
use timespec where existing ones use timeval and so are genuinely new even 
on 64-bit architectures, you'd end up needing to split 
__ASSUME_KERNEL_Y2038_SUPPORT into separate macros for the separate groups 
of syscalls.)
Joseph Myers - Sept. 25, 2018, 8:30 p.m.
On Tue, 25 Sep 2018, Arnd Bergmann wrote:

> riscv32 falls into this category: there is preliminary kernel support
> for it, but no upstream glibc. The riscv maintainers have indicated a
> preference that they would actually want to drop the 32-bit time_t
> syscalls from the kernel as well, since nobody is relying on them
> today. I don't think it makes a difference to glibc, so we'll discuss this
> among the kernel folks.
> 
> In general, we don't break established user ABIs as a rule, but we
> also have lots of precedent for changing interfaces when we are
> sure that there are no users that would complain about the change.

Depending on how long the glibc ports take to be ready (previously 
submitted, but without all the other upstream toolchain components being 
ready at the time), it could also apply to ARC and NDS32.  In the ARC 
case, the kernel port has been there for years, so unlike riscv32 I 
presume you couldn't remove the old syscalls from the kernel.
Palmer Dabbelt - Sept. 25, 2018, 9:51 p.m.
On Tue, 25 Sep 2018 13:14:38 PDT (-0700), Arnd Bergmann wrote:
> On Tue, Sep 25, 2018 at 9:36 PM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote:
>>
>> CC:ing Arnd re whether all 32-bit architectures will get 64-bit-time
>> kernel support.
>>
>> On Tue, 25 Sep 2018 17:25:39 +0000, Joseph Myers
>> <joseph@codesourcery.com> wrote :
>> > On Mon, 24 Sep 2018, Albert ARIBAUD wrote:
>> > Before we work out what the macro (or macros if more than one is needed)
>> > is called, and the semantics of it being defined or undefined, we need to
>> > have a clear understanding of the semantics.  And that in turn requires a
>> > clear understanding of what the future kernel interfaces will be.
>> >
>> > Could you provide a description of what the kernel interfaces will be in
>> > future for each of the following cases (and any other significantly
>> > different variants I've missed)?  Then, indicate whether you'd expect the
>> > __ASSUME_* macro or macros to be defined in each of those cases.
>> > Hopefully this will help clarify what the interfaces should look like
>> > within glibc.  (This information will also need to go in the proposed
>> > glibc commit messages for future versions of the present patch, and quite
>> > likely some of it should go in comments in glibc code.)
>> >
>> >
>> > 1a. Existing 64-bit architectures, where 64-bit time_t is the only variant
>> > supported, in both the kernel and (if those architectures already have
>> > glibc ports) glibc.
>> >
>> > My expectation is that these will *not* provide any new syscalls and will
>> > *not* provide any new __NR_* aliases for existing syscalls.  Is that
>> > correct?
>>
>> Yes, that is correct.
>
> I was undecided on this issue actually: it does make some sense to
> me to have the syscall macros be the same in the long run, so that
> glibc doesn't have to pick between __NR_clock_gettime and
> __NR_clock_gettime64 in a few years, after all supported kernels
> support __NR_clock_gettime64. Also, 64-bit architectures won't
> reuse the number space that we reserve for the new calls on 32-bit
> architectures, so the addition is essentially free.
>
> OTOH, it does seem a bit silly to have two syscall numbers that
> point to the same symbol.
>
> I don't have a strong preference here, and can do whichever
> you like better in glibc.
>
>> > If so, would the __ASSUME_* macro be defined for those architectures or
>> > not?  Whether it is or not, there must *not* be any new variables or
>> > internal functions defined in glibc at all relating to Y2038 support, or
>> > any additional levels of function calls / wrappers at runtime when
>> > time-related glibc functions are used, given that there are no Y2038
>> > problems for those architectures at present anyway.  (Avoiding such extra
>> > code and data might involve e.g. __TIMESIZE conditionals.  Naturally it's
>> > *also* desirable to design the implementation internals to reduce the
>> > number of places needing such conditionals.)
>> >
>> >
>> > 1b. New 64-bit architectures (not currently supported in the kernel).
>> >
>> > My expectation is that these will be the same as old ones - they will
>> > provide the existing syscalls (minus obsolete ones), under their existing
>> > names, not any new ones that explicitly reference 64-bit time.  Is that
>> > correct?  If so, I'd expect them to look exactly like case 1a in glibc.
>>
>> I think this is correct.
>
> See above.
>
>> > 2a. Existing 32-bit architectures, supported in both the kernel and glibc
>> > with 32-bit time_t.
>> >
>> > These will all need to gain new syscalls under new names, with the new
>> > macro defined when those syscalls are known to be available at runtime.
>>
>> Correct.
>
> Right.
>
>> > 2b. Existing 32-bit architectures, already supported in the kernel, but
>> > not supported in glibc until after the 64-bit time support is present in
>> > both places.
>> >
>> > >From the point of view of the kernel, these should be exactly like case
>> > 2a.  But from the point of view of glibc, they might be different - we
>> > might want to support only 64-bit time for them (so __TIMESIZE would be
>> > 64, and _TIME_BITS=64 would do nothing).  Is that what you'd intend for
>> > such new architectures in glibc?  If so, presumably the __ASSUME_* macro
>> > would still be defined for them, but the combination of that macro and
>> > __TIMESIZE == 64 might end up doing different things in some places?  And
>> > would the glibc port for such an architecture allow runtime fallback to
>> > 32-bit time syscalls, or would it also require a minimum kernel with
>> > 64-bit time support rather than allowing older kernels from before the
>> > glibc port was added?
>> >
>> > (Of course you can't really test this combination; it may fall to whoever
>> > adds the first such architecture port to glibc to get it working.)
>> >
>> > Another consideration for such architectures is whether you end up with
>> > the combination of 64-bit time and 32-bit file offsets for them (given
>> > _TIME_BITS=64 requires _FILE_OFFSET_BITS=64, but here you have 64-bit time
>> > without defining _TIME_BITS).  It might make sense for such architectures
>> > also to use 64-bit offsets unconditionally, like 64-bit architectures do,
>> > so that defining _FILE_OFFSET_BITS=64 for them only affects mangling for a
>> > few types, not layout.
>>
>> As you point out, I won't test for this combination, but yes, my
>> opinion is that 32-bit architectures which are supported in the kernel
>> but not yet in glibc should only use 64-bit time syscalls when glibc
>> support is added.
>
> riscv32 falls into this category: there is preliminary kernel support
> for it, but no upstream glibc. The riscv maintainers have indicated a
> preference that they would actually want to drop the 32-bit time_t
> syscalls from the kernel as well, since nobody is relying on them
> today. I don't think it makes a difference to glibc, so we'll discuss this
> among the kernel folks.
>
> In general, we don't break established user ABIs as a rule, but we
> also have lots of precedent for changing interfaces when we are
> sure that there are no users that would complain about the change.

Obviously I'm OK deferring to kernel policy here, but my understanding of the 
rv32 situation is that we decided the rv32 kernel ABI is not stable and will 
not be marked as stable until our glibc port is upstream -- much the same as we 
did for the rv64 port.  This came up outside the context of 32-bit time_t, but 
I forget what the actual issue is.  That's what I've been telling people in 
RISC-V land.

I think I'll just start a Linux thread about this, as like you said there isn't 
a whole lot of glibc involvement here.

>> > 3. New 32-bit architectures (new in both kernel and glibc after the
>> > addition of 64-bit time support for 32-bit architectures in the kernel).
>> >
>> > My expectation is that these will *only* have the new-named syscalls for
>> > 64-bit time, not the old-named syscalls that use 32-bit time on 32-bit
>> > systems (and not the old syscall names but pointing to syscalls that use
>> > 64-bit time, either).  Is that correct - new-named syscalls only for
>> > everything involving time on such architectures?
>>
>> I think this is correct.
>
> Yes, absolutely. Both csky and mips p32 will possibly fall into this
> category, but it depends on how soon we can complete the addition
> of the 64-bit time_t syscalls.
>
>> > > - #define it in sysdeps/unix/sysv/linux/kernel-features.h and then
>> > >   #undef it in sysdeps/unix/sysv/linux/*/kernel-features.h, and later
>> > >   when some architecture gets Y2038 syscall support, remove its #undef?
>> >
>> > I'd hope all 32-bit architectures get kernel support at the same time.
>> > Is that the intent, or is something else intended?
>>
>> Arnd would know this much better than I do.
>
> I have planned to do it that way in the past, but with csky, mips-p32
> and rv32 eager to change over as fast as they can, it seems more
> likely now that there will be two steps here:
>
> a) some architectures that only support 64-bit time_t from the start,
>      possibly in linux-4.21
> b) all other architectures supporting 64-bit time_t a little later, possibly
>     4.22. This depends on work by Firoz Khan that is still under discussion
>     at the moment.
>
> There are also still a few open questions that we would need to resolve
> in order to close in on the final ABI:
>
> - The timex  structure for clock_adjtime64. I'd like to use the
>    same version that x32 uses today, so we can avoid creating another
>    32-bit compat interface for it. If there are any concerns with that,
>    please let me know. In glibc, we will then have to change the
>    __syscall_slong_t members of timex to a new type that is the
>    same length as time_t.
>
> - Whether to update itimerval (setitimer/getitimer) and rusage
>   (getrusage, wait4, __kerrnel_waitid) or not. These only carry
>   relative times, and they are in an awkward format (timeval).
>   If we were to replace them, we'd probably want to use timespec
>   on the syscall ABI, but that in turn means that glibc still
>   requires a translation between the kernel structure and its
>   own POSIX compatible structure. I'd appreciate to hear any
>   opinions on this matter, one way or another, or alternative ideas.
>
> - Whether to harmonize the existing syscall tables across all
>   architectures while adding the new calls: I think this would be
>   a good time to ensure that all architectures support all syscalls
>   we have added over time, or at least define the number.
>   This includes missing recent additions (io_pgetevents, rseq,
>   fsinfo, ...) and those that may only exist as wrappers (ipc,
>   socketcall) instead of direct entry points.
>
> - In case we do harmonize the syscall tables, whether to go as
>   far as using the same numbers for all of the new calls across
>   the traditional architectures. E.g. clock_gettime64 could
>   become 400 on x86, sparc, ppc, mips, ia64, etc and be
>   followed by other 20 new calls with identical numbers.
>   For the generic syscall ABI (arm64, openrisc, riscv, arc, ...)
>   we'd probably use lower numbers to avoid a big gap, but at
>   least that makes it only two possible numbers instead of 12
>   for each call.
>
>        Arnd
arnd@arndb.de - Sept. 26, 2018, 7:20 a.m.
On Tue, Sep 25, 2018 at 10:31 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Tue, 25 Sep 2018, Arnd Bergmann wrote:
>
> > riscv32 falls into this category: there is preliminary kernel support
> > for it, but no upstream glibc. The riscv maintainers have indicated a
> > preference that they would actually want to drop the 32-bit time_t
> > syscalls from the kernel as well, since nobody is relying on them
> > today. I don't think it makes a difference to glibc, so we'll discuss this
> > among the kernel folks.
> >
> > In general, we don't break established user ABIs as a rule, but we
> > also have lots of precedent for changing interfaces when we are
> > sure that there are no users that would complain about the change.
>
> Depending on how long the glibc ports take to be ready (previously
> submitted, but without all the other upstream toolchain components being
> ready at the time), it could also apply to ARC and NDS32.  In the ARC
> case, the kernel port has been there for years, so unlike riscv32 I
> presume you couldn't remove the old syscalls from the kernel.

For ARC that is clearly the case, yes. For nds32, we have an
existing uclibc-ng mainline port that uses the current syscall
ABI, which I see as enough precedent that I would not consider
doing an incompatible change any more, but glibc can simply
pretend that the time32 interfaces never existed on this.

       Arnd
Albert ARIBAUD - Sept. 26, 2018, 8:06 a.m.
Hi Joseph,

On Tue, 25 Sep 2018 20:25:22 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Tue, 25 Sep 2018, Joseph Myers wrote:
> 
> > Yes, subject to the question of what's appropriate on 64-bit architectures 
> > where time_t always has been 64-bit and the existing names of syscalls, 
> > not the new ones, are used for all time-related syscalls.  If 
> > __ASSUME_KERNEL_Y2038_SUPPORT means the syscalls with the new names are 
> > guaranteed to be present, then it should be undefined in that case because 
> > only the old names will be present (but also the variable etc. relating to 
> > runtime tests for support should not be declared at all, so if any code 
> > with such tests is - wrongly - compiled on such an architecture, it will 
> > fail to compile).  
> 
> There is of course also a possible variant for 64-bit architectures if it 
> proves better for the implementation:
> 
> * Make a glibc-internal header #define all the __NR_* for the new syscall 
> names to point to the old names if the kernel headers don't do so.
> 
> * Define __ASSUME_KERNEL_Y2038_SUPPORT unconditionally for such 
> architectures, because the syscalls in question are in fact old ones so 
> always present at runtime.  (If the kernel headers might define the new 
> __NR_* names *and point them to new syscall numbers*, it's more 
> complicated, because in that case it would no longer be correct to assume 
> the syscalls are available with an old kernel, but it would be completely 
> useless to have runtime checks to decide between using old and new syscall 
> numbers for the same syscall.  Also, if there are new syscalls that e.g. 
> use timespec where existing ones use timeval and so are genuinely new even 
> on 64-bit architectures, you'd end up needing to split 
> __ASSUME_KERNEL_Y2038_SUPPORT into separate macros for the separate groups 
> of syscalls.)

I don't think 64-bit architectures will get the new __NR_* names, but
if they do, I think that they will point to the old numbers, i.e.,
Y2038 support should not introduce new syscalls on 64-bit
architectures (as these syscalls would basically be the same as
existing ones).

So I would tend to favor your variant approach above, as it makes the
semantics of __ASSUME_KERNEL_Y2038_SUPPORT simpler:

- if defined, we just use the new __NR_* names and 64-bit times, even
  for 64-bit architectures (with new names mapped to old names/numbers
  either by the kernel or by us);

- if undefined, we try the new names and numbers and on ENOSYS we fall
  back to the old names and numbers. 

Cordialement,
Albert ARIBAUD
3ADEV
Florian Weimer - Sept. 26, 2018, 8:18 a.m.
* Albert ARIBAUD:

> Hi Florian,
>
> On Tue, 25 Sep 2018 12:58:25 +0200, Florian Weimer <fweimer@redhat.com>
> wrote :
>
>> * Albert ARIBAUD:
>> 
>> > - one new boolean for every new feature, which libc can read/write.
>> >   Reading happens every time the feature is used.
>> >   Writing happens very rarely, once when first first using / testing for
>> >   the feature (e.g. at application start), once if using the feature
>> >   fails (e.g. a syscall returns ENOSYS).
>> >
>> > - two accessors (getter/setter) for every new feature if it must be
>> >   read/set from another glibc library than libc (e.g. librt).  
>> 
>> I'm still surprised that this is needed.  Why can't applications call
>> the function in question and react to a well-documented error code?
>
> These features are for glibc rather than for applications; they are
> here for glibc to remember whether a Y2038 feature is available in the
> kernel over which it currently runs.

Okay, that makes sense.

> Applications, on the other hand, would call the 64-bit-time interface
> regardless of the feature state. Whether this call would translate
> into 64-bit-time or 32-bit-time syscalls would be invisible to them. 

Presumably, there's still the matter of ioctl and ancillary messages on
sockets.

Thanks,
Florian
arnd@arndb.de - Sept. 26, 2018, 8:40 a.m.
On Wed, Sep 26, 2018 at 10:19 AM Florian Weimer <fweimer@redhat.com> wrote:
> * Albert ARIBAUD:
> > On Tue, 25 Sep 2018 12:58:25 +0200, Florian Weimer <fweimer@redhat.com>
> > Applications, on the other hand, would call the 64-bit-time interface
> > regardless of the feature state. Whether this call would translate
> > into 64-bit-time or 32-bit-time syscalls would be invisible to them.
>
> Presumably, there's still the matter of ioctl and ancillary messages on
> sockets.

Right, I don't think there is a solution for those; running an application
with 64-bit time_t on an old kernel is something we can't really support.
glibc can make it mostly work, and we can try to backport patches to
device drivers where needed, but this will remain incomplete.

My expectation however is that the kernel can return an appropriate
error code (-ENOTTY, -EINVAL, -ENOSYS) for each such case, so
at least it will be easy enough to debug.

Also, we have to make a hard requirement of using kernel
headers from a fixed version for building the application, so things
like ioctl command numbers, magic mmap() offsets and setsockopt
options can take the right values depending on sizeof(time_t)
to let the kernel know which ABI the user expects.

       Arnd
Albert ARIBAUD - Sept. 26, 2018, 8:48 a.m.
Hi Joseph,

On Wed, 19 Sep 2018 13:03:21 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:
> 
> > * New function __y2038_get_kernel_support() returns:
> >   * 0 if the underlying kernel does not support Y2038 at all
> >   * > 0 if the underlying kernel has some support for Y2038
> >   * < 0 if the underlying kernel support for Y2038 is broken
> > * New function __y2038_set_kernel_support() allows indicating
> >   a kernel's Y2038 support (or support failure)
> > * Default implementation (covering non-Linux kernels) always
> >   returns 0 (no support).  
> 
> There should be an __ASSUME_* macro that kernel-features.h defines when 
> the minimum kernel version has the required feature.  Calls to these APIs 
> need to become compile-time constants in that case, with the functions / 
> variables not existing in the glibc binaries at all.

If __ASSUME_KERNEL_Y2038_SUPPORT is defined, then variables and
functions should not be defined at all in the glibc binaries, but I
don't think we need to make calls to these APIs compile-constant in
that case, because there should not be any such calls.

Any code which would depend on __ASSUME_KERNEL_Y2038_SUPPORT to call
either the new 64-bit-time syscall or old 32-bit-time syscall would
basically follow this pattern:

  #ifdef __ASSUME_KERNEL_Y2038_SUPPORT
    unconditionally call new __NR_* syscall using 64-bit-time(s),
    with no fallback on ENOSYS;
  #else
    if __y2038_get_kernel_support() indicates support:
      call new __NR_* syscall with 64-bit time(s);
      if ENOSYS:
        call __y2038_set_kernel_support() to indicate failure;
        perform pre-call 64-to-32-bit time conversions if any;
        call old __NR_* syscall with 32-bit time(s);
        perform post-call 32-to-64-bit time conversions if any.
    else:
      perform pre-call 64-to-32-bit time conversions if any;
      call old __NR_* syscall with 32-bit time(s);
      perform post-call 32-to-64-bit time conversions if any.
  #endif

The 'then' part of the '#if' does not contain any calls to
__y2038_{get,set}_kernel_support() because there is no need for them.

More precisely, the utility of __y2038_get_kernel_support() and
__y2038_set_kernel_support() appears only when we could use either
32-bit-time or 64-bit-time syscalls. We want to try the 64-bit-time
syscalls first because we prefer them and they /may/ be available in
the underlying kernel, but as soon as we learn that 64-bit-time
syscalls are not provided, then we want to stop trying them, and go
straight to 32-bit-time syscalls.

So when __ASSUME_KERNEL_Y2038_SUPPORT is defined, we assume the
64-bit-time syscalls /are/ there, and we don't drop into using
32-bit-time-only anymore; and no falling back means no need to remember
whether we need to fall back later -- i.e., we don't need to call
__y2038_{get,set}_kernel_support() at all.

Cordialement,
Albert ARIBAUD
3ADEV
Albert ARIBAUD - Sept. 26, 2018, 8:53 a.m.
Hi Arnd,

Le Wed, 26 Sep 2018 10:40:48 +0200, Arnd Bergmann <arnd@arndb.de> a
écrit :

> Also, we have to make a hard requirement of using kernel
> headers from a fixed version for building the application, so things
> like ioctl command numbers, magic mmap() offsets and setsockopt
> options can take the right values depending on sizeof(time_t)
> to let the kernel know which ABI the user expects.

Since Y2038-proof glibc will require a minimum kernel version to
build that is Y2038-proof too (as glibc will need to use the new __NR_*
syscall names defined by the kernel). Isn't that requirement enough? 

Cordialement,
Albert ARIBAUD
3ADEV
arnd@arndb.de - Sept. 26, 2018, 9:02 a.m.
On Wed, Sep 26, 2018 at 10:54 AM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote:
>
> Hi Arnd,
>
> Le Wed, 26 Sep 2018 10:40:48 +0200, Arnd Bergmann <arnd@arndb.de> a
> écrit :
>
> > Also, we have to make a hard requirement of using kernel
> > headers from a fixed version for building the application, so things
> > like ioctl command numbers, magic mmap() offsets and setsockopt
> > options can take the right values depending on sizeof(time_t)
> > to let the kernel know which ABI the user expects.
>
> Since Y2038-proof glibc will require a minimum kernel version to
> build that is Y2038-proof too (as glibc will need to use the new __NR_*
> syscall names defined by the kernel). Isn't that requirement enough?

Yes, we just have to ensure that the headers contain both the
syscall number definitions and the updated driver headers. It
may be that we get the syscall definitions first (some driver interface
changes are still under discussion, or stalled), and one has to
ensure that they don't install older kernel headers together with
a glibc that has been built against the newer version.

     Arnd
Albert ARIBAUD - Sept. 26, 2018, 9:25 a.m.
Hi Arnd,

On Wed, 26 Sep 2018 11:02:55 +0200, Arnd Bergmann <arnd@arndb.de>
wrote :

> On Wed, Sep 26, 2018 at 10:54 AM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote:
> >
> > Hi Arnd,
> >
> > Le Wed, 26 Sep 2018 10:40:48 +0200, Arnd Bergmann <arnd@arndb.de> a
> > écrit :
> >  
> > > Also, we have to make a hard requirement of using kernel
> > > headers from a fixed version for building the application, so things
> > > like ioctl command numbers, magic mmap() offsets and setsockopt
> > > options can take the right values depending on sizeof(time_t)
> > > to let the kernel know which ABI the user expects.  
> >
> > Since Y2038-proof glibc will require a minimum kernel version to
> > build that is Y2038-proof too (as glibc will need to use the new __NR_*
> > syscall names defined by the kernel). Isn't that requirement enough?  
> 
> Yes, we just have to ensure that the headers contain both the
> syscall number definitions and the updated driver headers. It
> may be that we get the syscall definitions first (some driver interface
> changes are still under discussion, or stalled), and one has to
> ensure that they don't install older kernel headers together with
> a glibc that has been built against the newer version.

"One" here can only be the end user. The best glibc could do would
be to include usr/include/linux/version.h and check LINUX_VERSION_CODE
against a decided-upon minimum version, but maybe the kernel headers
are not there when the public glibc headers are included by an
application source file, so we can't even do that.

Cordialement,
Albert ARIBAUD
3ADEV
Joseph Myers - Sept. 26, 2018, 4:19 p.m.
On Wed, 26 Sep 2018, Albert ARIBAUD wrote:

> I don't think 64-bit architectures will get the new __NR_* names, but
> if they do, I think that they will point to the old numbers, i.e.,
> Y2038 support should not introduce new syscalls on 64-bit
> architectures (as these syscalls would basically be the same as
> existing ones).

This is where Arnd said in 
<https://sourceware.org/ml/libc-alpha/2018-09/msg00452.html> he was 
undecided.

Having new numbers for the old syscalls doesn't provide anything useful to 
glibc since we'd want in some cases to avoid using those new numbers.  
Having new names for the old syscall numbers is fairly harmless; it might 
simplify some code in glibc if it means __ASSUME_KERNEL_Y2038_SUPPORT can 
be defined for 64-bit, but it might also complicate things (glibc would 
need to define the new names to the old ones when building with old kernel 
headers, __ASSUME_KERNEL_Y2038_SUPPORT would probably need to be split 
into two if there are genuinely new syscalls for 64-bit for the itimerval 
/ rusage cases).

> - if undefined, we try the new names and numbers and on ENOSYS we fall
>   back to the old names and numbers. 

With of course compile-time conditionals to handle the case when the new 
names aren't defined at all, so we can only use the old syscalls without 
such runtime conditionals.
Joseph Myers - Sept. 26, 2018, 4:24 p.m.
On Wed, 26 Sep 2018, Albert ARIBAUD wrote:

>   #else
>     if __y2038_get_kernel_support() indicates support:
>       call new __NR_* syscall with 64-bit time(s);
>       if ENOSYS:
>         call __y2038_set_kernel_support() to indicate failure;
>         perform pre-call 64-to-32-bit time conversions if any;
>         call old __NR_* syscall with 32-bit time(s);
>         perform post-call 32-to-64-bit time conversions if any.
>     else:

This first part also needs further conditionals to disable it altogether 
if the __NR_* for the new syscall isn't defined.  (Actually it might just 
be the

>     if __y2038_get_kernel_support() indicates support:
>       call new __NR_* syscall with 64-bit time(s);
>       if ENOSYS:
>         call __y2038_set_kernel_support() to indicate failure;

that's conditional in the source code, and maybe some open/close braces, 
so that the logic for using the 32-bit syscalls only appears once.)

Patch

diff --git a/misc/Makefile b/misc/Makefile
index 9a87e81ae5..dd64bf256f 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -71,7 +71,7 @@  routines := brk sbrk sstk ioctl \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr getauxval ifunc-impl-list makedev \
-	    allocate_once
+	    allocate_once y2038-support
 
 generated += tst-error1.mtrace tst-error1-mem.out \
   tst-allocate_once.mtrace tst-allocate_once-mem.out
diff --git a/misc/Versions b/misc/Versions
index 900e4ffb79..e242bf7218 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -158,6 +158,10 @@  libc {
   GLIBC_2.26 {
     preadv2; preadv64v2; pwritev2; pwritev64v2;
   }
+  GLIBC_2.29 {
+    __y2038_get_kernel_support;
+    __y2038_set_kernel_support;
+  }
   GLIBC_PRIVATE {
     __madvise;
     __mktemp;
diff --git a/misc/y2038-support.c b/misc/y2038-support.c
new file mode 100644
index 0000000000..e401cb1112
--- /dev/null
+++ b/misc/y2038-support.c
@@ -0,0 +1,32 @@ 
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* By default glibc assumes the underlying kernel does not support Y2038 */ 
+int __default_y2038_get_kernel_support (void)
+{
+  return 0;
+}
+weak_alias (__default_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+/* By default glibc just ignores Y2038 support indication setting */ 
+int __default_y2038_set_kernel_support (int new with __attribute__ ((unused)))
+{
+  return 0;
+}
+weak_alias (__default_y2038_set_kernel_support, __y2038_set_kernel_support)
diff --git a/misc/y2038-support.h b/misc/y2038-support.h
new file mode 100644
index 0000000000..ec7891b63b
--- /dev/null
+++ b/misc/y2038-support.h
@@ -0,0 +1,36 @@ 
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Get Y2038 kernel support.
+ * 0 means no suppport
+ * > 0 means (some) support
+ * < 0 means support is broken
+ */
+extern int __y2038_get_kernel_support (void);
+
+/* Set Y2038 support.
+ * 0 means no suppport
+ * > 0 means (some) support
+ * < 0 means support is broken
+ * Architectures should call this with new > 0 as soon as they know that
+ * their underlying kernel has Y2038 support.
+ * Implementations should call this with new < 0 as soon as they detect
+ * that a Y2038 kernel support failure occurred.
+ * As a courtesy, the previous support indication is returned. */
+extern int __y2038_set_kernel_support (int new);
diff --git a/sysdeps/unix/sysv/linux/y2038-support.c b/sysdeps/unix/sysv/linux/y2038-support.c
new file mode 100644
index 0000000000..f325efc7d8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.c
@@ -0,0 +1,40 @@ 
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* By default the underlying Linux kernel is assumed not to support Y2038.
+ * Any Linux architecture may claim Y2038 kernel support by setting
+ * __y2038_linux_support.
+ */
+int __y2038_linux_support = 0;
+
+/* For Linux, Y2038 kernel support is determined by __y2038_linux_support  */
+
+int __linux_y2038_get_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
+strong_alias (__linux_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+int __linux_y2038_set_kernel_support (int new)
+{
+  int previous = __y2038_linux_support;
+  __y2038_linux_support = new;
+  return previous;
+}
+strong_alias (__linux_y2038_set_kernel_support, __y2038_set_kernel_support)
diff --git a/sysdeps/unix/sysv/linux/y2038-support.h b/sysdeps/unix/sysv/linux/y2038-support.h
new file mode 100644
index 0000000000..7dcbe0b313
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.h
@@ -0,0 +1,30 @@ 
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Indicates Y2038 support.
+ * 0 means no suppport
+ * > 0 means (some) support
+ * < 0 means support is broken
+ * Can be read directly from within libc linux-related files.
+ * Can be written non-zero to indicate support or lack thereof.
+ */
+extern int __y2038_linux_support;
+
+/* As a fallback, provide generic Y2038 support indication */
+#include <misc/y2038-support.h>