On Mon, Dec 06, 2021 at 11:56:19PM +0100, Alejandro Colomar (man-pages) wrote: > I (more or less) understand the deduction of why that happens on certain > systems, what I was wondering is if there's an intention behind that, or if > it's just an accident. Why not just use plain 'long' always as POSIX says > it should be. I don't see the feature part of this bug. > > 'long' is at least 32 bits, which > is enough for 1G. Was there ever a good reason for glibc to use 64 bits? It > seems like a wrong decision that is maintained for consistency. If that's it > I'm in favor of mentioning it in a Bugs section (as Jakub proposed), instead > of a Notes section. Maybe someone from glibc may give a rationale for this > deviation from POSIX. AFAICT, as you say, this isn't much more than a side-effect of using the amd64 ABI and not being too careful with how it interacts with the POSIX requirement (it's entirely feasible to re-wrap a user-space timespec, or even use the bitfield trick glibc already does to not have to do it), but then I'm far from an expert; indeed, maybe someone with more glibc involvement will know. Updating to Bugs for now, maybe we can downgrade later. > I'd add an explicit mention that this is for glibc, since it deviates from > the "Conforming to". Fair enough, though I don't actually know if this is glibc-exclusive. I assume it is, since I didn't find a timespec in the musl git repository and the linux uapi header has the straight-forward definition, but I can't be sure because I don't actually run (well, even know of) any x32 musl systems I could verify this on. > Maybe preceding the paragraph with "In/On (I never > knew if there goes in or on) glibc," would do. Out of those two: on (in would point to glibc internals), but I'd actually go for "Under", here, since glibc is an over-arching (literally) universe-defining context, rather than an add-on, or something build your program on top of. For my own curiosity: which preposition would you use in Spanish here? > On 12/6/21 23:03, наб wrote: > > +.br > We don't use '.br'. In this case I think just continuing in the same > paragraph would be fine (i.e., no break at all). > > +In reality, the field ends up being defined as: > Here I'd add a blank line with '.PP'. > > +.EX > > +.in +4 > Please, revert the order of .in and .EX. > It's meaningless, but I prefer consistency. See man-pages(7), which shows > this order, and also the following: > > $ grep -rn '^\.EX$' -A1 man? | grep '\.in' | wc -l > 2 > $ grep -rn '^\.EX$' -B1 man? | grep '\.in' | wc -l > 1048 > > > One of those 2 cases was this patch. Sure, sure, and sure > > +#if !(__x86_64__ && __ILP32__ /* == x32 */) > > Now I notice: > > Shouldn't this use defined()? > > #if !(defined(__x86_64__) && defined(__ILP32__) /* == x32 */) Eeeeh, not really? That's functionally identical but, like, very verbose for no good reason. > Also, I prefer to avoid complexity in mentally parsing the ifs, so I'd > reorder it to remove the negation: > > #if defined(__x86_64__) && defined(__ILP32__) /* == x32 */ > long long tv_nsec; > #else > long tv_nsec; > #endif long first made more sense when this was in-line, but I agree, non-negated is better. > And also note a cosmetic minor thing: at least two spaces before a comment. Sure Updated scissor-patch below. I've also fixed some grammar errors toward the tail-end of the (now) Bugs section. Best, наб -- >8 -- There are three files that govern userspace struct timespec on glibc: 1. bits/wordsize.h, defining: (a) __WORDSIZE to 32 on ILP32 and 64 on LP64 (b) on x32: __SYSCALL_WORDSIZE to 64 2. bits/timesize.h, defining (a) __TIMESIZE to __WORDSIZE, except on x32 where it's 64 3. bits/types/struct_timespec.h, declaring struct timespec as: struct timespec { __time_t tv_sec; /* Seconds. */ #if __WORDSIZE == 64 \ || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) \ || __TIMESIZE == 32 __syscall_slong_t tv_nsec; /* Nanoseconds. */ #else # if __BYTE_ORDER == __BIG_ENDIAN int: 32; /* Padding. */ long int tv_nsec; /* Nanoseconds. */ # else long int tv_nsec; /* Nanoseconds. */ int: 32; /* Padding. */ # endif #endif }; this has two side-effects: struct timespec (a) is always sizeof==time_t+8, and (b) has tv_nsec as __syscall_slong_t *and* !is_same<__syscall_slong_t, long> if using LP64 syscalls on an ILP32 system, i.e. on x32. This means, that the simplified struct timespec { time_t tv_sec; /* Seconds */ long tv_nsec; /* Nanoseconds [0 .. 999999999] */ }; declaration is *invalid* for x32, where struct timespec::tv_nsec is an int64_t (long long). Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@xxxxxxxxxxxxxxxxxx> --- man7/system_data_types.7 | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/man7/system_data_types.7 b/man7/system_data_types.7 index 1e6a3f74c..66c9a5d3d 100644 --- a/man7/system_data_types.7 +++ b/man7/system_data_types.7 @@ -1553,6 +1553,37 @@ Describes times in seconds and nanoseconds. .IR "Conforming to" : C11 and later; POSIX.1-2001 and later. .PP +.IR Bugs : +Under glibc, +.I tv_nsec +is the +.I syscall +long, though this affects only fringe architectures like X32, +which is ILP32, but uses the LP64 AMD64 syscall ABI. +In reality, the field ends up being defined as: +.PP +.in +4 +.EX +#if __x86_64__ && __ILP32__ /* == x32 */ + long long tv_nsec; +#else + long tv_nsec; +#endif +.EE +.in +.PP +This is a long-standing and long-enshrined +.UR https://sourceware.org/bugzilla/show_bug.cgi?id=16437 +glibc bug +.I #16437 +.UE , +and an incompatible extension to the standards; +however, as even a 32-bit +.I long +can hold the entire +.I tv_nsec +range, it's always safe to forcibly down-cast it to the standard type. +.PP .IR "See also" : .BR clock_gettime (2), .BR clock_nanosleep (2), -- 2.30.2
Attachment:
signature.asc
Description: PGP signature