Re: [PATCH v8] futex_waitv.2: new page
From: Alejandro Colomar <alx@kernel.org>
Date: 2026-02-14 20:03:08
Hi, On 2026-02-14T20:30:37+0100, наб wrote:
On Sat, Feb 14, 2026 at 06:32:17PM +0100, Alejandro Colomar wrote:quoted
quoted
diff --git u/man/man2/futex_waitv.2 p/man/man2/futex_waitv.2 new file mode 100644 index 000000000..a1eeb8ce8 --- /dev/null +++ p/man/man2/futex_waitv.2@@ -0,0 +1,421 @@[...]quoted
+.SH SYNOPSIS +.nf +.BR "#include <linux/futex.h>" " /* Definition of " FUTEX* " constants */"Out of curiosity, why are some macros FUTEX2_* instead of FUTEX_*? (if you know)They call the futex_*() syscalls "futex2", in contrast to the futex(FUTEX_*) family which is (retronymically) version 1 futex; futex2-specific macros start with FUTEX2_, the original futex macros started with just FUTEX_.
Thanks!
quoted
quoted
+.B EINVAL +.B FUTEX2_NUMA +was set in +.IR waiters []. flags , +and the NUMA word +(which is the same size as the futex word) +is too small to contain the index of the biggest NUMA domain +(for example, +.B FUTEX2_SIZE_U8 +and there are more than 255 NUMA domains).Is it 255 or 256? I assume it's a 0-based index, so I'd expect there to fit 256 indices in a u8.kernel/futex/futex.h: int bits = 8 * futex_size(flags); // 8 u64 max = ~0ULL; // 0xFFFF`FFFF`FFFF`FFFF max >>= 64 - bits; // 0xFF if (nr_node_ids >= max) return false; which is first true when nr_node_ids is 0xFF, so "FUTEX2_SIZE_U8 and at least 255", actually. Also this variable is "/possible/ NUMA domains" apparently.
Hmmm.
Scissor-patch below. Best, -- >8 -- From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= <redacted> Date: Tue, 10 Feb 2026 21:32:19 +0100 Subject: [PATCH v8] futex_waitv.2: new page Signed-off-by: Ahelenia Ziemiańska <redacted> --- Range-diff against v7: 1: da50b4733 ! 1: c63cce1ec futex_waitv.2: new page
[...]
@@ man/man2/futex_waitv.2 (new)
+.P
+.\" SRC BEGIN (futex_waitv.c)
+.EX
++#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <linux/futex.h>
@@ man/man2/futex_waitv.2 (new)
+ struct futex_waitv waiters[countof(futexes)] = {};
+ int i;
+\&
-+ getentropy(init, sizeof(init));
++ if(getentropy(init, sizeof(init)))Space after structural keywords.
++ err(EXIT_FAILURE, "getentropy");
+ init[0] = init[1] = init[2];
+ for (i = 0; i < countof(futexes); ++i) {
+ printf("%" PRIu8 "\[rs]t", init[i]);
+ atomic_init(&futexes[i], init[i]);
-+ pthread_create(&(pthread_t){}, NULL, worker, &futexes[i]);
++ pthread_create(&(pthread_t) {}, NULL, worker, &futexes[i]);This is not a cast, so it should not have a space.
+ }
-+ putchar('\[rs]n');
++ putchar(\[aq]\[rs]n\[aq]);
+\&
+ for (i = 0; i < countof(futexes); ++i) {
+ waiters[i].val = futexes[i];
-+ waiters[i].uaddr = (uintptr_t)&futexes[i];
++ waiters[i].uaddr = (uintptr_t) &futexes[i];
+ waiters[i].flags = FUTEX2_SIZE_U32 | FUTEX2_PRIVATE;
+ }
+ for (;;) {[...]
quoted hunk ↗ jump to hunk
man/man2/futex_waitv.2 | 422 +++++++++++++++++++++++++++++++++++++++++ man/man7/futex.7 | 9 +- 2 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 man/man2/futex_waitv.2diff --git u/man/man2/futex_waitv.2 p/man/man2/futex_waitv.2 new file mode 100644 index 000000000..6835434b4 --- /dev/null +++ p/man/man2/futex_waitv.2
[...]
+.SH EXAMPLES
[...]
+int
+main(void)
+{[...]
+ if(getentropy(init, sizeof(init)))
+ err(EXIT_FAILURE, "getentropy");
+ init[0] = init[1] = init[2];
+ for (i = 0; i < countof(futexes); ++i) {
+ printf("%" PRIu8 "\[rs]t", init[i]);
+ atomic_init(&futexes[i], init[i]);
+ pthread_create(&(pthread_t) {}, NULL, worker, &futexes[i]);Not a cast.
+ }
+ putchar(\[aq]\[rs]n\[aq]);
+\&
+ for (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 (;;) {
+ struct timespec timeout;
+ int woke;
+\&
+ clock_gettime(CLOCK_MONOTONIC, &timeout);
+ timeout.tv_sec += 1;
+\&
+ woke = my_futex_waitv(waiters, countof(futexes), 0, &timeout, CLOCK_MONOTONIC);
+ if (woke == \-1 && (errno != EAGAIN && errno != EWOULDBLOCK))
+ break;
+\&
+ for (i = 0; i < countof(futexes); ++i) {
+ if (futexes[i] != waiters[i].val)
+ printf("%" PRIu32 "%s", futexes[i], i == woke ? "!" : "");
+ putchar(\[aq]\[rs]t\[aq]);
+ }
+ putchar(\[aq]\[rs]n\[aq]);
+\&
+ for (i = 0; i < countof(futexes); ++i)
+ waiters[i].val = futexes[i];
+ }
+ fprintf(stderr, "%s\[rs]n", strerror(errno));
This looks like 'perror("")', doesn't it?
Although, I'd use err(3) instead, which correctly fails instead of
returning 0, right?
err(EXIT_FAILURE, "my_futex_waitv");
Have a lovely night!
Alex
quoted hunk ↗ jump to hunk
+} +.EE +.\" SRC END +.SH SEE ALSO +.BR futex (2), +.BR FUTEX_WAIT (2const), +.BR FUTEX_WAKE (2const), +.BR futex (7) +.P +Kernel source file +.I Documentation/userspace-api/futex2.rstdiff --git u/man/man7/futex.7 p/man/man7/futex.7 index 51c5d5d9b..d271144ff 100644 --- u/man/man7/futex.7 +++ p/man/man7/futex.7@@ -45,7 +45,9 @@ .SS Semantics Any futex operation starts in user space, but it may be necessary to communicate with the kernel using the .BR futex (2) -system call. +or +.BR futex_waitv (2) +system calls. .P To "up" a futex, execute the proper assembler instructions that will cause the host CPU to atomically increment the integer.@@ -72,7 +74,9 @@ .SS Semantics .P The .BR futex (2) -system call can optionally be passed a timeout specifying how long +and +.BR futex_waitv (2) +system calls can optionally be passed a timeout specifying how long the kernel should wait for the futex to be upped. In this case, semantics are more complex and the programmer is referred@@ -107,6 +111,7 @@ .SH NOTES .SH SEE ALSO .BR clone (2), .BR futex (2), +.BR futex_waitv (2), .BR get_robust_list (2), .BR set_robust_list (2), .BR set_tid_address (2),-- 2.39.5
-- <https://www.alejandro-colomar.es>
Attachments
- signature.asc [application/pgp-signature] 833 bytes