Hi Arnd, On Wed, 22 Feb 2017 16:39:53 +0100, Arnd Bergmann <[email protected]> wrote :
> On Wed, Feb 22, 2017 at 9:05 AM, Albert ARIBAUD <[email protected]> > wrote: > > Hi all, > > > > I have produced a fifth draft of what will eventually become the Y2038 > > design document: > > > > https://sourceware.org/glibc/wiki/Y2038ProofnessDesign?rev=115 > > > > Relative to the previous draft: > > > > * It makes explicit that the implementation should allow the same > > application source code to build unchanged whether the default for > > time size is 32-bit (_TIME_BITS undefined or unequal to 64) or > > 64-bit (_TIME_BITS defined equal to 64). > > > > * Security issues considerations have been added (thanks to Carlos > > O'Donnel). > > > > * Timestamps and IOCTLs sections have been expanded. > > > > * Implementation examples for types has been added. > > > > * Implementation examples for APIs has been added. > > > > As always, comments welcome. > > I found a few minor inaccuracies: > > You have classified sched_rr_get_interval() as y2038-compatible, but > getrusage() as incompatible. I think these are both in one category, > either incompatible or a third category: we pass only intervals > here, so there won't be an overflow but redefining timeval still results > in an incompatible ABI, unless the structures are redefined in terms > of 32-bit types instead of time_t/timeval/timespec. Actually, sched_rr_get_interval deserves a fourth category, known as 'in a quantum state', because depending on where you look in the document, it is either compatible or incompatible, due to a copy-paste failure. :) Joke apart, thanks for pointing it out and raising the point. My opinion is as follows: 1. Right now sched_rr_get_interval takes a struct timespec as an argument; 2. One goal of the project is that source code which works with 32-bit time should work unchanged if compiled with default time size set to 64 bits; 3. This means the 64-bit version of sched_rr_get_interval should keep explecting a (now 64-bit) 'struct timespec'; 4. This in turn makes the ABIs of the 32- and 64-bit versions of sched_rr_get_interval mutually incompatible, since the actual types involed would be either the 32-bit time 'struct timespec' or the 64-bit time 'struct timespec64'; 5. Ergo, sched_rr_get_interval should be classified as Y2038-incompatible. > I've discussed the kernel side for "Y2038-incompatible socket > timestamping" with Deep a while ago, and I think we came to a > new conclusions for what would be the best approach. I'll let her > comment here. > > For "Y2038-compatible types", please clarify whether time32_t > and time64_t (and related types) are internal-only types or visible > to applications through header files. I assume they are internal > only, but it is not 100% clear. Related to that, what is the expected > definition of time32_t on architectures that never had a 32-bit time_t, > such as existing 64-bit architectures? Is it left undefined and > all code referring to time32_t compiled conditionally? (written after reading Joseph's reply, and type names adapted accordingly) Yes, there would be two internal types, __time_t and __time64_t with sizes invariant with respect to default type size, whereas time_t, in the user facing public API, would be defined as either __time_t or __time64_t depending on which time bit size the user code would choose For instance, with difftime: - the existing, 32-bit-time version would be defined as double __difftime(__time_t time1, __time_t time0) ... - the new, 64-bit-time version would be defined as double __difftime64(__time64_t time1, __time64_t time0); - for user code which does not define _TIME_BITS=64 at compile time, GLIBC would emit [what amounts to] the following declaration: double __difftime(__time_t time1, __time_t time0); typedef __time_t time_t; __REDIRECT(difftime,(time_t time1, time_t time0),__difftime) so that when the user code would say time_t t1, t2; ...; difftime(t1, t2); this would amount to __time_t t1, t2; ...; __difftime(t1, t2); - for user code which defines _TIME_BITS=64 at compile time, GLIBC would emit [what amounts to] the following declarations: double __difftime64(__time64_t time1, __time64_t time0); typedef __time64_t time_t; __REDIRECT(difftime,(time_t time1, time_t time0),__difftime64) so that when the user code would say time_t t1, t2; ...; difftime(t1, t2); this would turn into __time64_t t1, t2; ...; difftime64(t1, t2); (should I rename the current __time_t to a more explicit __time32_t?) As far as 64-bit architectures are concerned: - pure 64-bit architectures already have a 64-bit time_t, and are out of the scope of my project; a 64-bit GLIBC is assumed to be Y2038- compatible as far as APIs go (there may be bugs though; again, if I see any, I'll raise an GLIC issue but outside of this project). - this leaves the case of a 64-bit architecture kernel providing a 32-bit ABI to 32-bit code. I am not planning on supporting such a scenario. > In "Y2038-compatible struct timespec", replace "microseconds" > with "nanoseconds. Oops. Fixed in revision 118. > Also, it's worth pointing out the known problems > with the padding: > - on big-endian systems, any code doing a variation of > "struct timespec ts = { seconds, nanos };" is broken because > it assigns the nanoseconds to the wrong struct member. > The example code is nonconforming as neither POSIX nor C11 > require a particular order of the struct members, but I could also > easily find examples of existing programs doing this. Note that > NetBSD, OpenBSD and Windows have no padding but do use > 64-bit time_t. > - If the padding is uninitialized, we have to explicitly zero it before > calling a kernel function that assumes the 64-bit layout. This can > be done in glibc before calling into the kernel, or at the kernel > entry (where my last patch set does it), but it is awkward either > way. > Unfortunately, there doesn't seem to be a good solution here > for either of the two problems. Maybe someone else has more > ideas. Using a pointer type for the padding would at least > cause a compile-time warning for broken code, other solutions > might require GCC extensions or break C11 in another way. Agreed on the whole line, and I will add these points in the document. However, this makes me consider an option which would keep source code as happy as possible: keep tv_nsec a long even in struct timespec64 (so the struct would be 12 bytes: 8-byte tv_sec, 4-byte tv_nsec). It would be ABI-incompatible with 64-bit code, but would conform to Posix, and the same exact user source code would then compile equally well in all three cases: 32-bit time 64-bit time on 32-bit arch, 64-bit arch, including the struct initializers you mentioned above. There would be a rough edge left when running 32-bit arch, 64-bit time user code over a 64-bit arch GLIBC and kernel, because then we'd have to copy between 64-bit and 32-bit nanosecond fields, but then again, it is not a scenario I am aiming for. > I'll comment on the kernel/glibc incompatibilities section tomorrow, > need to collect my thoughts there some more. Thanks! > Arnd Cordialement, Albert ARIBAUD 3ADEV _______________________________________________ Y2038 mailing list [email protected] https://lists.linaro.org/mailman/listinfo/y2038
