Thread (49 messages) 49 messages, 5 authors, 2026-02-18

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.2
diff --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.rst
diff --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

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help