Re: [PATCH v3 3/3] system_data_types.7: note struct timespec::tv_nsec type for x32 and portability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux