[RFC PATCH 0/2] Linux: Add futex_waitv syscall wrapper
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Aug 18 17:57:30 GMT 2026
On 14/08/26 15:36, André Almeida wrote:
> Hi folks,
>
> Based on a talk on last LPC by Carlos O'Donell[1], I'm sending this patch as a
> starting point to add the futex_waitv() syscall wrapper.
>
> I tried to base myself on the work done for others wrappers, but I see that
> there are missing details in my implementation, so I'm seeking guidance on how
> to approach this.
>
> Thanks!
> André
>
> [1] https://lpc.events/event/19/contributions/2220/
This triggered two regressions from our CI [1]:
FAIL: misc/check-installed-headers-c
[...]
:: sys/futex.h
[...]
:::: -D_XOPEN_SOURCE=700
In file included from ../sysdeps/unix/sysv/linux/sys/futex.h:6,
from ../include/sys/futex.h:2,
from /tmp/cih_test_lKjACY.c:10:
../include/struct___timespec64.h:5:23: error: ‘struct timespec’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
5 | # define __timespec64 timespec
| ^~~~~~~~
../sysdeps/unix/sysv/linux/sys/futex.h:22:49: note: in expansion of macro ‘__timespec64’
22 | unsigned int flags, const struct __timespec64 *timeout,
[...]
FAIL: misc/tst-futex
original exit status 127
The check-installed-headers-c is a namespace pollution, which seems most likely
from the bare '<struct___timespec64.h>' inclusion.
The misc/tst-futex is most likely a build issue, since the patch does not export
the futex_waitv from 'Versions', nor it updates the libc.abilist to check whether the
symbols is correctly being exported. How did you test this?
There were other issues, like missing Copyright headers and minor formatting issue.
But I think the main issue is it feels incomplete and clunky to export a new futex
interface where we still don't have a proper futex wrapper. In the testcase itself
you had to use syscall to issue the FUTEX_WAKE.
I think we should define and export a plain futex wrapper before adding this
extension. I recall that one point of contention was that due the kABI futex
ABI, a more extensible wrapper through varargs would be preferable than a one
with pre-defined operations.
However, our experience with varargs interfaces showed that it can be painful
(like ioctl, prctl, etc); and futex operation are currently limited that I
think we can set on a operation API.
The main consumers of this possible futex interface are lock/condvar/synchronization
implementers (C++ std::atomic::wait, language runtimes, Rust-style parking) who need
async-signal-safety, and don't want errno clobbering or cancellation cleanup
interacting with their own state machines.
So I think we can start with something like:
--
enum
{
FUTEX_FLAG_PRIVATE = 0, /* Default: process-private (fast path). */
FUTEX_FLAG_SHARED = 1 << 0, /* Cross-process, word in a shared mapping. */
};
int futex_wait (uint32_t *futexp, uint32_t expected, unsigned int flags);
int futex_timedwait (uint32_t *futexp, uint32_t expected,
clockid_t clockid, const struct timespec *abstime,
unsigned int flags);
int futex_wake (uint32_t *futexp, int count, unsigned int flags);
int futex_requeue (uint32_t *futexp, uint32_t expected,
int nwake, uint32_t *targetp, int nrequeue,
unsigned int flags);
--
* The function returns the error code, which maps to the INTERNAL_SYSCALL_CALL.
Different than the pthread wrappers, EINTR is reported rather than auto-retried.
* Timeouts are absolute-only, with an explicit clockid_t (restricted to
CLOCK_MONOTONIC and CLOCK_REALTIME, NULL = infinite). This hides the worst
kernel wart (which we handle on nptl/futex-internal.c): FUTEX_WAIT takes a
relative CLOCK_MONOTONIC timeout while FUTEX_WAIT_BITSET takes an absolute one,
and FUTEX_CLOCK_REALTIME composes inconsistently across ops.
The implementation always uses FUTEX_WAIT_BITSET with FUTEX_BITSET_MATCH_ANY
underneath, exactly like __futex_abstimed_wait64 does.
* Since it is a new interface, support only for 64-bit time_t.
* Explicitly excluded broken interfaces: FUTEX_FD, FUTEX_REQUEUE;
* Not provided:
- FUTEX_WAKE_OP: error-prone, and glibc itself abandoned its only use when the
condvar was rewritten;
- Bitset matching: exist in practice as a vehicle for absolute timeouts, which
the API provides directly;
- FUTEX_WAIT_REQUEUE_PI / FUTEX_CMP_REQUEUE_PI: subtle ordering requirements,
and error-prone.
- Robust futexes: single per-thread resource glibc already owns for
PTHREAD_MUTEX_ROBUST; and exporting would possible create conflicts on
*who* owns the list.
* What I am not sure, but seems doable:
- PI futexes (FUTEX_LOCK_PI/TRYLOCK_PI/UNLOCK_PI): the kernel dictates a lot of
userland ABI (owner TID, FUTEX_WAITERS, FUTEX_OWNER_DIED), so exporting them means
documenting that protocol as ABI.
I will try to create POC so we can check if it makes sense.
[1] https://patchwork.sourceware.org/project/glibc/patch/20260814183612.1780736-3-andrealmeid@igalia.com/
>
> André Almeida (2):
> Linux: Add futex_waitv
> misc: tst-futex: Create futex test
>
> include/sys/futex.h | 4 ++
> sysdeps/unix/sysv/linux/Makefile | 3 +
> sysdeps/unix/sysv/linux/futex_waitv.c | 32 +++++++++
> sysdeps/unix/sysv/linux/sys/futex.h | 24 +++++++
> sysdeps/unix/sysv/linux/tst-futex.c | 93 +++++++++++++++++++++++++++
> 5 files changed, 156 insertions(+)
> create mode 100644 include/sys/futex.h
> create mode 100644 sysdeps/unix/sysv/linux/futex_waitv.c
> create mode 100644 sysdeps/unix/sysv/linux/sys/futex.h
> create mode 100644 sysdeps/unix/sysv/linux/tst-futex.c
>
More information about the Libc-alpha
mailing list