Date: Fri, 24 Jun 2016 20:55:01 +1000 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Peter Wemm <peter@wemm.org> Cc: freebsd-arch@freebsd.org Subject: Re: PowerPC 64-bit time_t Message-ID: <20160624194454.D1013@besplex.bde.org> In-Reply-To: <575A48D3.3090008@wemm.org> References: <3FB65E20-0376-4041-86DE-F8CAB7F37314@freebsd.org> <20160609193128.GB34204@spindle.one-eyed-alien.net> <575A48D3.3090008@wemm.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 10 Jun 2016, Peter Wemm wrote: > On 6/9/16 3:31 PM, Brooks Davis wrote: >> On Thu, Jun 09, 2016 at 01:41:52PM -0400, Justin Hibbits wrote: >>> At 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. >>> with 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. > I 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. > > A short summary of the issues for i386: > > * 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. > eg: 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. > * 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. > Do 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. > Also, 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. > I'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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160624194454.D1013>