Post by Peter WemmPost by Brooks DavisPost by Justin HibbitsAt the devsummit earlier today I mentioned for FreeBSD 12 wanting 64-
bit time_t across the board. It was pointed out that the only ones
FreeBSD-12 certainly doesn't want the bloat and ABI breakage of 64-bit
time_t. The 32nd bit is not needed before FreeBSD-23 in 2038. The 33rd
bit is not needed before FreeBSD-57 in 2106.
Post by Peter WemmPost by Brooks DavisPost by Justin Hibbitswith 32-bit time_t are i386 and powerpc (32-bit). I've made the
changes necessary for at least kernel (world is still building right
now), but it's obviously an ABI and KBI incompatible change.
Addressing KBI is a nonissue, as that's expected to break at major
releases. ABI is another issue. I'm unsure how to properly address
ABI breakage -- bumping libc's .so version, or reversion all symbols
that use something with time_t, or something else. If I can address
it before the code freeze, it could be done for FreeBSD 11, which
leaves about 6 hours from now.
For i386, the only practical option is going to be a new TARGET_ARCH and
likely ELF machine type.
The only practical option for i386 is to change to unsigned time_t before
2038 and hope that i386 goes away before that runs out in 2106. Changing
to uint32_t time_t mainly requires doing something with times before the
Epoch. These are unsupported in POSIX, but are supposed to work back to
1902 with int32_t in FreeBSD, except 1 second before the Epoch is the
same as the error code (time_t)(-1) so it doesn't work right.
Post by Peter WemmI investigated this when I did 64 bit time_t on amd64 - the chances of
getting this to work on i386 are ... problematic.. to say the least.
* sparc64, amd64 and ia64 were "easy" because there was an actual register to
implement it. Calling conventions plaster over vast quantities of sins and
carelessness and make it Just Work by in spite of it. You forget a function
prototype and it still works. i386 has to do it with "long long" which
requires discipline. Miss a prototype and it falls flat.
On 64-bit arches, most of the space bloat for 64-bit time_t is unavoidable
because:
- args are expanded to 64 bits
- struct timeval was originally misdesigned as having members tv_sec and
tv_usec of type long. These longs were basically an implementation of
int_least32_t before <stdint.h> existed. tv_usec only needs to go up
to 10**9, so it should have type precisely int_least32_t or possibly
int32_t to give an invariant ABI. POSIX copied this mistake and added
many more when it made the mistake of inventing struct timespec. ts_nsec
stil has type long. This gives the stupid ABI that on 64-bit arches
with 32-bit time_t, struct timespec starts with a 32-bit time_t, then
has 32 bits of padding, then has a 64-bit long with only 32-bits used.
Later, POSIX broke the ABI for struct timeval to match -- it changed
'long tv_sec' to time_t tv_sec.
So using 64-bit time_t costs little on 64-bit arches.
Post by Peter Wemmeg: if you miss the prototype for a function returning time_t the language
defaults the return value to "int". On ia64, amd64 and sparc64, this is
actually returned as a 64 bit value (native register) and it actually gets
the full 64 bit value. For i386, this doesn't happen - you always get
truncation. You won't find out until it actually matters. This problem will
keep turning up forever. The top half will be returned in the %edx secondary
return register and will be ignored.
Forever only afer 2038 :-). And between 2038 and 2106, 32-bit time_t will
still almost work without making it officially unsigned -- discarding the
top half still gives a value that is correct when the sign bit is
interpreted as a value bit, provided it was set using overflow magic as
a value bit.
Post by Peter Wemm* classic 3rd party code used "long" and "time_t" interchangeably. We get
away with this on ia64, amd64 and sparc64 just fine. This will also lead to
truncation on i386 with 64 bit time_t when it matters.
* Sloppy prototyping leads to stack misalignment on i386 with "long long".
Arguments are rounded up to 32 bit alignment, so char/short/int/long
confusion on i386 for function calling protocol mostly is repaired as a side
effect. 'long long' doesn't get this treatment for function calls - any
sloppiness will be punished with arguments being shifted. Unlike the
truncation above, this is pretty quick to find. You won't have to wait 5-10
years for them to shake out.
Most of the FreeBSD base tree was fixed for this during the Alpha era (which
used "int" for time_t on a 64 bit platform because mktime() in libc wasn't 64
bit safe at all). However, when you go near ports and 3rd party code the
situation is rather grim. The code out there is terrible.
I maintain that while we got away with it for machines that the calling
conventions masked the pain for sloppy and legacy programming, this is not
the case for architectures like i386. The pain will never end.
I agree.
Post by Peter WemmDo you want to be the one who has to explain why something like openssl isn't
rejecting expired certificates because openssl happens to confuse long/time_t
internally somewhere in the X509 validator? (Note: I'm not saying it is
broken, but I don't have a hard time imagining that it could..).
The question is if changing 32-bit time_t to unsigned is also too painful.
I think it won't make much difference until 2038 when the 32nd bit is
actually used.
Post by Peter WemmAlso, don't forget all the compat_freebsd32 layers. You'll have to realign
all the arguments because 'long long' is 32 bit aligned, and a 64 bit long
(aka time_t) is 64 bit aligned.
Also, they need to do something better than truncation to convert 64-bit
time_t to 32-bit time_t. The only reasonable thing to do between 2038
and 2106 is to use uint32_t for the compatibility layers and teach old
applications to expect this.
Then there are the compat_{linux,svr*} layers. All representations and
conversions must be compatible with whatever the emulated OS does.
Post by Peter WemmI'm sure it could be done for a science project, but I wouldn't want to go
anywhere near it for something that would be relied upon. This would be a
project that gives gifts that will keep on giving.
Bruce