Message ID | 20180919071303.26636-1-albert.aribaud@3adev.fr |
---|---|
State | New |
Headers | show |
Series | Y2038: provide kernel support indication | expand |
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.)
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?
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
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.
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
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
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[
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
* 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
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
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.
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
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
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).
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.)
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.
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
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
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
* 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
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
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
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
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
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
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.
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.)
Hi Arnd, On Tue, 25 Sep 2018 22:14:38 +0200, Arnd Bergmann <arnd@arndb.de> 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'd say this double naming would be justified by the will to transition from the 'old' to the 'new' symbols. > I don't have a strong preference here, and can do whichever > you like better in glibc. There does not seem to have been any other comment on this for a while, so, do we go for this approach? That is: - on 64-bit architectures, the kernel will define _NR symbols identical to those added for Y2038, so that, for instance, on X86_64, there will be an _NR_clock_gettime64 symbol (which will point to the same syscall number as _NR_clock_gettime does). - on 64-bit architectures, GLIBC will set __ASSUME_KERNEL_Y2038_SUPPORT once the minimal kernel supported version for these architectures provides the 'new' syscall symbols. - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is defined, then GLIBC assumes the 'new' syscall symbols exist and can be used. - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is NOT defined, then GLIBC will try to use new syscalls for which a _NR symbol is provided by the build-time kernel, and on ENOSYS, will fallback to old syscalls. Cordialement, Albert ARIBAUD 3ADEV
On Wed, 5 Dec 2018, Albert ARIBAUD wrote: > - on 64-bit architectures, GLIBC will set __ASSUME_KERNEL_Y2038_SUPPORT > once the minimal kernel supported version for these architectures > provides the 'new' syscall symbols. > > - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is defined, > then GLIBC assumes the 'new' syscall symbols exist and can be used. > > - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is NOT defined, > then GLIBC will try to use new syscalls for which a _NR symbol is > provided by the build-time kernel, and on ENOSYS, will fallback to old > syscalls. There should be *no* new code in the glibc compiled for 64-bit architectures - no ENOSYS fallback, because none is needed. __ASSUME_* is always about features to assume to be present in the kernel used at runtime, not about what __NR_* symbols are defined (however, the kernel headers used for compiling glibc must always be at least as recent as the specified --enable-kernel version).
On Wed, Dec 5, 2018 at 12:49 PM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote: > On Tue, 25 Sep 2018 22:14:38 +0200, Arnd Bergmann <arnd@arndb.de> wrote : > > On Tue, Sep 25, 2018 at 9:36 PM Albert ARIBAUD <albert.aribaud@3adev.fr> wrote: > > 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. > > > > I don't have a strong preference here, and can do whichever > > you like better in glibc. > > There does not seem to have been any other comment on this for a while, > so, do we go for this approach? That is: > > - on 64-bit architectures, the kernel will define _NR symbols identical > to those added for Y2038, so that, for instance, on X86_64, there > will be an _NR_clock_gettime64 symbol (which will point to the same > syscall number as _NR_clock_gettime does). There are a few new considerations for things that happened over the last few months, so I'd still like to get more people involved before we finally decide on this one: - For cleaning up the kernel headers to make them more easily usable in glibc, I think it makes a lot of sense to define the new new macro names (as I said above). If we do that, maybe we should do it for other system calls (not time related) as well, in particular fcntl64, {f,}statfs64, {f,}truncate64, llseek, sendfile64, fstat{at,}64, mmap2, and fadvise64 as well as the associated structures. I already plan to do it independently for socketcall and ipc, which should be replaced with the separate entry points whenever we have the recent enough kernel. - The work that Firoz Khan did for generating the asm/unistd.h kernel headers and syscall tables on all architectures makes it a little awkward to redirect new syscall macros to existing numbers, as the table file format uses the number as the primary key. The most logical way to do this in the kernel now is actually to have the newly assigned number point to the same syscall implementation on all architectures, both 32-bit and 64-bit. Not providing the number on 64-bit at all is fairly easy, but the redirect would require a permanent workaround on ppc, sparc, parisc, s390, and riscv as well as any future 64-bit architectures. - Any Lutomirksi has some ideas for cleaning up the x86 syscall table, which may be relevant here. Adding him to Cc. > - on 64-bit architectures, GLIBC will set __ASSUME_KERNEL_Y2038_SUPPORT > once the minimal kernel supported version for these architectures > provides the 'new' syscall symbols. > > - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is defined, > then GLIBC assumes the 'new' syscall symbols exist and can be used. We have a couple of system calls that we add even on 64-bit architectures, including statx() and likely the new version of waitid()/getrusage(). I think for those the logic has to be different, so a 64-bit architecture will have to e.g. fall back to calling fstatat() when statx() is unavailable on an older kernel. > - on all architectures, if __ASSUME_KERNEL_Y2038_SUPPORT is NOT defined, > then GLIBC will try to use new syscalls for which a _NR symbol is > provided by the build-time kernel, and on ENOSYS, will fallback to old > syscalls. I think it's important that we only do this when we are called from an application with 64-bit time_t: When a user calls gettimeofday() with 64-bit time_t, that should try clock_gettime64(2) and fall back to clock_gettime(2) or gettimeofday(2) if that is unavailable. However an application using gettimeofday() with a 32-bit time_t should directly call gettimeofday(2) in the kernel but not try clock_gettime64() first. Without that distinction, the kernel cannot return -ENOSYS if we configure it to break compatibility with 32-bit time_t interfaces and the application might seem to work correctly despite being broken in 2038. Arnd
On Wed, 5 Dec 2018, Arnd Bergmann wrote: > The most logical way to do this in the kernel now is actually to > have the newly assigned number point to the same syscall > implementation on all architectures, both 32-bit and 64-bit. If you have (redundant) new numbers on 64-bit, glibc should not use those at all on 64-bit until the minimum kernel version is new enough to be sure they are available, to avoid unnecessary runtime fallback code. Cf. how on socketcall architectures it made sense to keep using just socketcall for accept4 / recvmmsg / sendmmsg, rather than using the separate syscalls with runtime fallback to socketcall (in the cases where syscalls were added later than socketcall support), unless the configured minimum kernel version is recent enough to ensure the syscall is available. (That does not prevent glibc having local #undef / #define to be able to use the new *names* unconditionally while still using the old numbers, if that proves useful.) > I think it's important that we only do this when we are called from > an application with 64-bit time_t: When a user calls gettimeofday() > with 64-bit time_t, that should try clock_gettime64(2) and fall back > to clock_gettime(2) or gettimeofday(2) if that is unavailable. However > an application using gettimeofday() with a 32-bit time_t should > directly call gettimeofday(2) in the kernel but not try clock_gettime64() > first. Without that distinction, the kernel cannot return -ENOSYS > if we configure it to break compatibility with 32-bit time_t interfaces > and the application might seem to work correctly despite being > broken in 2038. By design, all nontrivial 32-bit time interfaces in glibc for 32-bit architectures should end up as simple wrappers round the implementations using 64-bit time internally, to avoid duplication of complicated code (previous versions of the Y2038 patches e.g. duplicated hundreds of lines of pthread_mutex_timedlock implementation, which is clearly not a maintainable approach). That means many 32-bit interfaces *will* end up using 64-bit syscalls (with fallback to 32-bit if the 64-bit syscalls are unavailable at runtime), even if some simple functions that really are just one syscall for 32-bit still call the old syscall.
On Wed, Dec 5, 2018 at 2:48 PM Joseph Myers <joseph@codesourcery.com> wrote: > On Wed, 5 Dec 2018, Arnd Bergmann wrote: > > > I think it's important that we only do this when we are called from > > an application with 64-bit time_t: When a user calls gettimeofday() > > with 64-bit time_t, that should try clock_gettime64(2) and fall back > > to clock_gettime(2) or gettimeofday(2) if that is unavailable. However > > an application using gettimeofday() with a 32-bit time_t should > > directly call gettimeofday(2) in the kernel but not try clock_gettime64() > > first. Without that distinction, the kernel cannot return -ENOSYS > > if we configure it to break compatibility with 32-bit time_t interfaces > > and the application might seem to work correctly despite being > > broken in 2038. > > By design, all nontrivial 32-bit time interfaces in glibc for 32-bit > architectures should end up as simple wrappers round the implementations > using 64-bit time internally, to avoid duplication of complicated code > (previous versions of the Y2038 patches e.g. duplicated hundreds of lines > of pthread_mutex_timedlock implementation, which is clearly not a > maintainable approach). That means many 32-bit interfaces *will* end up > using 64-bit syscalls (with fallback to 32-bit if the 64-bit syscalls are > unavailable at runtime), even if some simple functions that really are > just one syscall for 32-bit still call the old syscall. That would make it very hard to deploy a glibc based system with strict y2038 requirements. If we can no longer guarantee the basic assumption that old applications keep using the old system calls, then I think we instead need a way to build glibc itself without support for the 32-bit time_t interfaces, e.g. using a --disable-time32 configuration switch to force a link-time error for any application or library that has not been built against the 64-bit time_t interfaces. The default would of course remain providing backwards compatibility with all applications to allow a gradual migration from 32-bit time_t to 64-bit time_t. If all 32-bit time_t calls are just wrappers around either the internal implementation using 64-bit time_t or around a simple system call, then it should at least be easy to make them optional for users that need them not work. Would that be something you can do? Arnd
On Wed, 5 Dec 2018, Arnd Bergmann wrote: > That would make it very hard to deploy a glibc based system > with strict y2038 requirements. If we can no longer guarantee the > basic assumption that old applications keep using the old system > calls, then I think we instead need a way to build glibc itself without > support for the 32-bit time_t interfaces, e.g. using a --disable-time32 > configuration switch to force a link-time error for any application > or library that has not been built against the 64-bit time_t interfaces. (There's never been a guarantee of keeping using the same system calls. Cf. people trying to restrict the system calls some code can use and running into issues with moves to use e.g. *at syscalls unconditionally on all architectures to implement the non-*at functions.) The set of interfaces that involve 32-bit time_t or other structures including it is well-defined; an external checker can examine the dynamic symbol table of any dynamically linked 32-bit application or shared library to see if it has references to any of the symbols in question, without needing to run the code at all (and so detect issues in code that might not be frequently executed, not just in whatever code runs when you're testing for 32-bit time uses). (Or if you control the build of the whole system, do a local change to make a glibc header use #error if _TIME_BITS is not defined to 64.) I'd expect it to be a long time before we might consider making 32-bit time_t (and thus 32-bit off_t) subject to something like --enable-obsolete-rpc / --enable-obsolete-nsl being needed to make the 32-bit interfaces available at (static) link time at all.
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>