Hi, On 2026-02-17T15:31:29+0100, наб wrote: > On Tue, Feb 17, 2026 at 02:07:42PM +0100, Alejandro Colomar wrote: > > On 2026-02-16T21:43:14+0100, наб wrote: > > > +.TP > > > +.B EINVAL > > > +.I *timeout > > > +is denormal (before epoch or > > > +.I tv_nsec > > > +more than 999\[aq]999\[aq]999). > > I suspect .tv_nsec < 0 is also denormal, and it being a long, that's > > certainly possible, right? Should we specify a range? > Hm, yeah: [...] > I hadn't considered the cast also checks for <0. > > Scissor-patch below. I'm applying the patch, amended with the following. diff --git c/man/man2/futex_waitv.2 i/man/man2/futex_waitv.2 index f0553698e42a..7e336fec830d 100644 --- c/man/man2/futex_waitv.2 +++ i/man/man2/futex_waitv.2 @@ -4,7 +4,7 @@ .\" .TH futex_waitv 2 (date) "Linux man-pages (unreleased)" .SH NAME -futex_waitv \- wait for FUTEX_WAKE operation on multiple futexes +futex_waitv \- wait for FUTEX_WAKE operation on a vector of futexes The NAME section should try to explain the name. Thus, using the word 'vector' in the description of the name seems better, as it clarifies why it has a trailing 'v'. .SH LIBRARY Standard C library .RI ( libc ,\~ \-lc ) @@ -15,20 +15,20 @@ .SH SYNOPSIS .B #include .B #include .P -.BR "long syscall(" "unsigned int n;" -.BI " SYS_futex_waitv, struct futex_waitv " waiters [ n ], -.BI " unsigned int " n ", unsigned int " flags , -.BI " const struct timespec *_Nullable " timeout ", clockid_t " clockid ");" +.BR long\~syscall( unsigned\~int\~n; +.BI " SYS_futex_waitv, struct\~futex_waitv\~" waiters [ n ], +.BI " unsigned\~int\~" n ", unsigned\~int\~" flags , +.BI " const\~struct\~timespec\~*_Nullable\~" timeout ", clockid_t\~" clockid ); I'm planning a global change in SYNOPSIS to use SY/YS. This will reduce the work. .fi .P .EX .B "#include " .P struct futex_waitv { - u64 val; /* Expected value at \f[I]uaddr\f[] */ - u64 uaddr; /* User address to wait on */ - u32 flags; /* Flags for this waiter */ - u32 __reserved; /* Align to u64 */ + u64 val; /* Expected value at \f[I]uaddr\f[] */ + u64 uaddr; /* User address to wait on */ + u32 flags; /* Flags for this waiter */ + u32 __reserved; /* Align to u64 */ I used a tab. Also, two spaces between type and name, and between code and comment. }; .EE .SH DESCRIPTION @@ -300,6 +300,7 @@ .SH EXAMPLES .B !\& indicates the futex that woke up each .BR futex_waitv (). +.P You forgot the P. .in +4 .EX .RB $\~ ./futex_waitv @@ -361,29 +362,28 @@ .SH EXAMPLES int main(void) { - _Atomic uint32_t futexes[10]; - uint8_t init[countof(futexes)]; - struct futex_waitv waiters[countof(futexes)] = {}; - int i; + _Atomic uint32_t futexes[10]; + uint8_t init[countof(futexes)]; + struct futex_waitv waiters[countof(futexes)] = {}; Aligned the names. \& if (getentropy(init, sizeof(init))) err(EXIT_FAILURE, "getentropy"); init[0] = init[1] = init[2]; - for (i = 0; i < countof(futexes); ++i) { + for (int i = 0; i < countof(futexes); ++i) { I prefer C99 loop variables. printf("%w8u\[rs]t", init[i]); atomic_init(&futexes[i], init[i]); pthread_create(&(pthread_t){}, NULL, worker, &futexes[i]); } putchar(\[aq]\[rs]n\[aq]); \& - for (i = 0; i < countof(futexes); ++i) { + for (int i = 0; i < countof(futexes); ++i) { waiters[i].val = futexes[i]; waiters[i].uaddr = (uintptr_t) &futexes[i]; waiters[i].flags = FUTEX2_SIZE_U32 | FUTEX2_PRIVATE; } for (;;) { + int woke; struct timespec timeout; - int woke; \& clock_gettime(CLOCK_MONOTONIC, &timeout); timeout.tv_sec += 1; @@ -392,14 +392,14 @@ .SH EXAMPLES if (woke == \-1 && (errno != EAGAIN && errno != EWOULDBLOCK)) err(EXIT_FAILURE, "my_futex_waitv"); \& - for (i = 0; i < countof(futexes); ++i) { + for (int i = 0; i < countof(futexes); ++i) { if (futexes[i] != waiters[i].val) printf("%w32u%s", futexes[i], i == woke ? "!" : ""); putchar(\[aq]\[rs]t\[aq]); } putchar(\[aq]\[rs]n\[aq]); \& - for (i = 0; i < countof(futexes); ++i) + for (int i = 0; i < countof(futexes); ++i) waiters[i].val = futexes[i]; } } I see some diagnostics from Clang, which I suspect I should just silence; let me know your opinion: .tmp/man/man2/futex_waitv.2.d/futex_waitv.c:36:13: error: implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary [clang-diagnostic-atomic-implicit-seq-cst,-warnings-as-errors] 36 | usleep(*futex * 10000); | ^ .tmp/man/man2/futex_waitv.2.d/futex_waitv.c:37:13: error: implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary [clang-diagnostic-atomic-implicit-seq-cst,-warnings-as-errors] 37 | *futex *= 2; | ^ I have little knowledge about atomics, so can't judge, but the code seems good to me. Please confirm. Cheers, Alex --