adjust struct timespec definition to be time64-ready
authorRich Felker <dalias@aerifal.cx>
Sun, 20 Oct 2019 07:27:58 +0000 (03:27 -0400)
committerRich Felker <dalias@aerifal.cx>
Sun, 20 Oct 2019 07:27:58 +0000 (03:27 -0400)
for time64 support on 32-bit archs, the kernel interfaces use a
timespec layout padded to match the representation of a pair of 64-bit
values, which requires endian-specific padding.

use of an ordinary, non-bitfield, named member for the padding is
undesirable because, on big endian archs, it would alter the
interpretation of traditional (non-designated) initializers of the
form {s,ns}, initializing the padding instead of the tv_nsec member.
unnamed bitfield members solve this problem by not taking part in
initialization, and were the expected solution when the kernel
interfaces were designed. however, they also have further advantages
which we take advantage of here:

positioning of the padding could be controlled by having a
preprocessor conditional with separate definitions of struct timespec
for little and big endian, but whether padding should appear at all is
a function of whether time_t is larger than long. this condition is
not something the preprocessor can determine unless we were to define
a new macro specifically for that purpose.

by using unnamed bitfield members instead of ordinary named members,
we can arrange for the size of the padding to collapse to zero when it
should not be present, just by using sizeof(time_t) and sizeof(long)
in the bitfield width expression, which can be any integer constant
expression.

include/alltypes.h.in

index c47c8bf7afd7044ede79402c05f2313a1b09943b..e9b29afcfa6806b2a8633e5d591f3d9dfa944592 100644 (file)
@@ -38,7 +38,7 @@ TYPEDEF void * timer_t;
 TYPEDEF int clockid_t;
 TYPEDEF long clock_t;
 STRUCT timeval { time_t tv_sec; suseconds_t tv_usec; };
-STRUCT timespec { time_t tv_sec; long tv_nsec; };
+STRUCT timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
 
 TYPEDEF int pid_t;
 TYPEDEF unsigned id_t;