[PATCH v3 3/3] system_data_types.7: note struct timespec::tv_nsec type for x32 and portability
Alejandro Colomar (man-pages)
alx.manpages@gmail.com
Tue Dec 7 00:52:52 GMT 2021
Hi, Zack!
On 12/7/21 01:18, Zack Weinberg wrote:
> Depending on the kernel, the architecture, the ABI, and the state of _TIME_BITS, the format of `struct timespec` as expected by system calls may be any of
>
> struct timespec { int32_t tv_sec; int32_t tv_nsec; };
> struct timespec { int64_t tv_sec; int64_t tv_nsec; };
> struct timespec { int64_t tv_sec; int32_t __padding; int32_t tv_nsec; }
> struct timespec { int64_t tv_sec; int32_t tv_nsec; int32_t __padding; }
>
> These may be incompatible with using bare `long` for tv_nsec in the user space headers. The problem cases are when the kernel expects option 2 but user space's `long` is only 32 bits wide, or if the kernel expects option 3 or 4 when `long` is 64 bits wide and the endianness of `long` doesn't agree with the position of the padding. I don't remember which ABIs actually manifest an incompatibility, but I remember this being discussed repeatedly during the project to make 64-bit time_t available to ILP32 ABIs.
>
> The C library CANNOT paper over the incompatibility by converting formats in the syscall wrappers, because `struct timespec` objects get embedded in an unbounded set of `ioctl` parameter blocks, `sendmsg` ancillary data structures, etc. etc. etc. We can't even make a list.
>
> Personally I consider the situation a defect in POSIX and C11; the definition of `struct timespec` should always have been
>
> struct timespec { time_t tv_sec; nsec_t tv_nsec; };
I can agree with that.
>
> where nsec_t is an integer type that can represent the range [0, 10**9). Last time this came up, Joseph didn't think there was any chance of persuading either the Austin Group or WG14 to make this change, unfortunately.
Okay, I can understand that.
How about defining ns[ec[onds]]_t (and possibly ms[ec[onds]]_t) in
glibc, and using them wherever ms or ns are used, such as in this case,
instead of a random type?
I think since glibc already ignores POSIX, it could go a bit further and
use an interface that is consistent (use nseconds_t always instead of
sometimes long sometimes long long), more readable than POSIX (a
variable of type nseconds_t already tells you a lot about it), and again
consistent (since we already have useconds_t, using nseconds_t would add
consistency to the types used in <time.h>.
Also, that would make clear that you should cast it to long to print it
(and using pointers would already make sure that you have the correct
pointer using a nseconds_t one). And of course, if a program wants to
be portable, it can just typedef it to long when using other libcs not
using nseconds_t.
Thanks,
Alex
--
Alejandro Colomar
Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/
More information about the Libc-alpha
mailing list