[glibc/azanella/futex-wrappers] linux: Add futex_waitv
Adhemerval Zanella via Glibc-cvs <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f1f9d36769be8ebc43f642eb6a9bcdc97767047b commit f1f9d36769be8ebc43f642eb6a9bcdc97767047b Author: Adhemerval Zanella <[email protected]> Date: Wed Aug 19 15:55:53 2026 -0300 linux: Add futex_waitv Add a wrapper for the futex_waitv system call to <sys/futex.h>: struct futex_waiter { uint64_t val; uint64_t uaddr; uint32_t flags; uint32_t __reserved; }; int futex_waitv (const struct futex_waiter *waiters, unsigned int nwaiters, unsigned int flags, clockid_t clockid, const struct timespec *abstime); It blocks on up to FUTEX_WAITV_MAX (128) futexes at the same time until any of them is woken. On success it returns the array index of the woken futex; on failure it returns -1 and sets errno. The timeout is absolute, measured against CLOCK_REALTIME or CLOCK_MONOTONIC. The struct futex_waiter has the same layout as the kernel struct futex_waitv and each entry carries the kernel FUTEX2_* flags. The only extra handling is the negative absolute timeout, which the kernel rejects with EINVAL and the wrapper reports as ETIMEDOUT. The underlying system call only supports 64-bit time_t and so does the wrapper. Checked on x86_64-linux-gnu and i686-linux-gnu. Diff: --- NEWS | 4 + include/sys/futex.h | 5 + manual/threads.texi | 85 ++++++++- sysdeps/unix/sysv/linux/Makefile | 13 ++ sysdeps/unix/sysv/linux/Versions | 1 + sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 + sysdeps/unix/sysv/linux/arc/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/csky/libc.abilist | 1 + sysdeps/unix/sysv/linux/futex_waitv.c | 38 ++++ sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 + sysdeps/unix/sysv/linux/i386/libc.abilist | 1 + .../unix/sysv/linux/loongarch/ilp32/libc.abilist | 1 + .../unix/sysv/linux/loongarch/lp64/libc.abilist | 1 + sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist | 1 + sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist | 1 + sysdeps/unix/sysv/linux/microblaze/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/microblaze/le/libc.abilist | 1 + .../unix/sysv/linux/mips/mips32/fpu/libc.abilist | 1 + .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist | 1 + .../unix/sysv/linux/mips/mips64/n32/libc.abilist | 1 + .../unix/sysv/linux/mips/mips64/n64/libc.abilist | 1 + sysdeps/unix/sysv/linux/or1k/libc.abilist | 1 + .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist | 1 + .../linux/powerpc/powerpc32/nofpu/libc.abilist | 1 + .../sysv/linux/powerpc/powerpc64/be/libc.abilist | 1 + .../sysv/linux/powerpc/powerpc64/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist | 1 + sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist | 1 + sysdeps/unix/sysv/linux/s390/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist | 1 + sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist | 1 + sysdeps/unix/sysv/linux/sys/futex.h | 50 ++++++ sysdeps/unix/sysv/linux/tst-futex-consts.py | 71 ++++++++ sysdeps/unix/sysv/linux/tst-futex-waitv-time64.c | 1 + sysdeps/unix/sysv/linux/tst-futex-waitv.c | 197 +++++++++++++++++++++ sysdeps/unix/sysv/linux/x86_64/64/libc.abilist | 1 + sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 42 files changed, 496 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 805a71b639..eec3907c71 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ Major new features: the futex system call and provide the blocking building block for implementing custom synchronization primitives. +* On Linux, the futex_waitv function has been added. It allows waiting + on multiple futexes at the same time, reporting the index of the woken + one. + Deprecated and removed features, and other changes affecting compatibility: [Add deprecations, removals and changes affecting compatibility here] diff --git a/include/sys/futex.h b/include/sys/futex.h index 602096a738..ec19fcd042 100644 --- a/include/sys/futex.h +++ b/include/sys/futex.h @@ -21,6 +21,11 @@ extern int __futex_timedwait_time64 (uint32_t *futexp, uint32_t expected, unsigned int flags) __nonnull ((1)); libc_hidden_proto (__futex_timedwait_time64) +extern int futex_waitv (const struct futex_waiter *waiters, + unsigned int nwaiters, unsigned int flags, + const struct __timespec64 *abstime, + clockid_t clockid) + __nonnull ((1)); # endif # endif /* !_ISOMAC */ diff --git a/manual/threads.texi b/manual/threads.texi index 16c716f0ab..fffd1fabb9 100644 --- a/manual/threads.texi +++ b/manual/threads.texi @@ -1582,7 +1582,8 @@ the kernel to use faster process-local bookkeeping. Without it, the futex word may be accessed by multiple processes through a shared memory mapping (@code{MAP_SHARED}). Waiters and wakers of one futex word must agree on this flag. The value follows the kernel -@code{FUTEX_PRIVATE_FLAG}. +@code{FUTEX_PRIVATE_FLAG}, so the same value is used by the +@code{futex_waitv} per-waiter flags. @deftypefun int futex_wait (uint32_t *@var{futexp}, uint32_t @var{expected}, unsigned int @var{flags}) @standards{Linux, sys/futex.h} @@ -1675,6 +1676,88 @@ same address, @var{nwake} or @var{nrequeue} are negative, or @end table @end deftypefun +@deftp {Data Type} {struct futex_waiter} +@standards{Linux, sys/futex.h} +Describes one futex to wait on in a call to @code{futex_waitv}. It +has the same layout as the kernel @code{struct futex_waitv} and the +following members: + +@table @code +@item uint64_t val +The value the futex word is expected to contain, as for +@code{futex_wait}. + +@item uint64_t uaddr +The address of the futex word. + +@item uint32_t flags +The kernel @code{FUTEX2_*} flags for this futex word: +@code{FUTEX2_SIZE_U32}, optionally combined with @code{FUTEX2_PRIVATE} +(equal to @code{FUTEX_PRIVATE_FLAG}) if the futex word is only used by +threads of the calling process, @code{FUTEX2_NUMA} if the futex word +is followed by a second 32-bit word holding the NUMA node id of the +kernel state (with @code{FUTEX_NO_NODE} letting the kernel choose the +node), and @code{FUTEX2_MPOL}. + +@item uint32_t __reserved +Reserved for future use; must be zero. +@end table +@end deftp + +@deftypevr Macro int FUTEX_WAITV_MAX +@standards{Linux, sys/futex.h} +The maximum number of elements of the array passed to @code{futex_waitv}, + currently 128. +@end deftypevr + +@deftypefun int futex_waitv (const struct futex_waiter *@var{waiters}, unsigned int @var{nwaiters}, unsigned int @var{flags}, const struct timespec *@var{abstime}, clockid_t @var{clockid}) +@standards{Linux, sys/futex.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Wait on all of the @var{nwaiters} futex words described by the array +@var{waiters}, blocking until any one of them is woken (or until a +spurious wake-up). Each futex word is checked against the expected +value recorded in its array entry, atomically with respect to +concurrent futex operations, as for @code{futex_wait}. + +The wait is bounded by the absolute time @var{abstime} measured +against the clock @var{clockid}, which must be @code{CLOCK_REALTIME} +or @code{CLOCK_MONOTONIC}. If @var{abstime} is a null pointer, the +call blocks without a timeout. + +The @var{flags} argument is the flags argument of the underlying +system call and is passed to the kernel unchanged; the system call +currently supports no flags, so it must be zero. + +The return value is the array index of one of the woken futex words, +or @minus{}1 with @code{errno} set to one of the following error +codes. + +@table @code +@item EAGAIN +A futex word did not contain the value expected by its array entry at +the time of the call. + +@item EINTR +The wait was interrupted by a signal handler. + +@item ETIMEDOUT +The absolute time @var{abstime} passed before any futex word was +woken. + +@item EINVAL +@var{nwaiters} is zero or greater than @code{FUTEX_WAITV_MAX}, a futex +word is not aligned to four bytes, a @code{flags} member is not valid, +or @var{clockid} is not a supported clock. + +@item ENOSYS +The kernel does not support the @code{futex_waitv} system call, which +was added in Linux 5.16. +@end table + +This function only operates on 64-bit @code{time_t} and is only declared +when @code{time_t} is a 64-bit type. +@end deftypefun + @c FIXME these are undocumented: @c pthread_atfork @c pthread_attr_destroy diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index cbe979f37a..12898e7049 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -77,6 +77,7 @@ sysdep_routines += \ futex_requeue \ futex_timedwait \ futex_wait \ + futex_waitv \ futex_wake \ fxstat \ fxstat64 \ @@ -205,6 +206,7 @@ tests += \ tst-fanotify \ tst-fdopendir-o_path \ tst-futex \ + tst-futex-waitv \ tst-getauxval \ tst-gettid \ tst-gettid-kill \ @@ -282,6 +284,7 @@ tests-time64 += \ tst-clock_adjtime-time64 \ tst-epoll-time64 \ tst-futex-time64 \ + tst-futex-waitv-time64 \ tst-ntp_adjtime-time64 \ tst-ntp_gettime-time64 \ tst-ntp_gettimex-time64 \ @@ -390,6 +393,16 @@ $(objpfx)tst-pidfd-consts.out: ../sysdeps/unix/sysv/linux/tst-pidfd-consts.py < /dev/null > $@ 2>&1; $(evaluate-test) $(objpfx)tst-pidfd-consts.out: $(sysdeps-linux-python-deps) +tests-special += \ + $(objpfx)tst-futex-consts.out \ + # tests-special +$(objpfx)tst-futex-consts.out: ../sysdeps/unix/sysv/linux/tst-futex-consts.py + $(sysdeps-linux-python) \ + ../sysdeps/unix/sysv/linux/tst-futex-consts.py \ + $(sysdeps-linux-python-cc) \ + < /dev/null > $@ 2>&1; $(evaluate-test) +$(objpfx)tst-futex-consts.out: $(sysdeps-linux-python-deps) + tests-special += \ $(objpfx)tst-mount-consts.out \ # tests-special diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index b417759862..bd92f21d9d 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -350,6 +350,7 @@ libc { %endif futex_timedwait; futex_wait; + futex_waitv; futex_wake; } GLIBC_PRIVATE { diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 9ac3743c8d..738626576c 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2778,4 +2778,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 93781d00f1..53085aa5d0 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -3125,6 +3125,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index f081a512c2..3bde0417c9 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2539,4 +2539,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index 43b75f779a..1c9c1cdc26 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -2832,6 +2832,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index 0dd5e4948f..811a07e242 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -2829,6 +2829,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index c7675ff2ef..4280091906 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2816,4 +2816,5 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/futex_waitv.c b/sysdeps/unix/sysv/linux/futex_waitv.c new file mode 100644 index 0000000000..5f0ca9057f --- /dev/null +++ b/sysdeps/unix/sysv/linux/futex_waitv.c @@ -0,0 +1,38 @@ +/* Wait on multiple futexes. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <sys/futex.h> +#include <sysdep.h> + +int +futex_waitv (const struct futex_waiter *waiters, unsigned int nwaiters, + unsigned int flags, const struct __timespec64 *abstime, + clockid_t clockid) +{ + int r; + if (__glibc_unlikely (abstime != NULL && abstime->tv_sec < 0)) + r = -ETIMEDOUT; + else + r = INTERNAL_SYSCALL_CALL (futex_waitv, waiters, nwaiters, flags, + abstime, clockid); + return INTERNAL_SYSCALL_ERROR_P (r) + ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r) + : r; +} diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index 70957e8d70..07a11c8a05 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2853,6 +2853,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index 0543cc2540..47d4ab3ee2 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -3036,6 +3036,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/loongarch/ilp32/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/ilp32/libc.abilist index 74b16c137f..4be7871d11 100644 --- a/sysdeps/unix/sysv/linux/loongarch/ilp32/libc.abilist +++ b/sysdeps/unix/sysv/linux/loongarch/ilp32/libc.abilist @@ -2290,4 +2290,5 @@ GLIBC_2.44 wscanf F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist index 2962b730e8..c86486b76b 100644 --- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist @@ -2299,4 +2299,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 96c17703fd..4bd809f238 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -2812,6 +2812,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index a392bf3a3a..e0556e4a4f 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2979,6 +2979,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index 1c419e0558..aa959e7d89 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2865,4 +2865,5 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index 236b0a9949..1ffb895b90 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2862,4 +2862,5 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index 59673b7709..40390d67c3 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2942,6 +2942,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 2cf11e9bd9..f0b9120c7f 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2940,6 +2940,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index 12fcf6c276..fdd3b120a4 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2948,6 +2948,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index d2056aa028..cec2301f61 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2849,6 +2849,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist index 7b82f1b2c8..98bdfd38d3 100644 --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist @@ -2289,4 +2289,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 6ace1864a0..cbddfdb962 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -3169,6 +3169,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index 556cb13f78..fd3deb9994 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -3214,6 +3214,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index aede41f65e..3147bba3c0 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2922,6 +2922,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index 60ee39b40c..c87ef1e840 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2998,4 +2998,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index 3760aa9c2e..3ad3deb6f4 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2542,4 +2542,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index 4f19643514..bd10acb85b 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2742,4 +2742,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F diff --git a/sysdeps/unix/sysv/linux/s390/libc.abilist b/sysdeps/unix/sysv/linux/s390/libc.abilist index 76d21db2a8..657bcfa87c 100644 --- a/sysdeps/unix/sysv/linux/s390/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/libc.abilist @@ -2959,6 +2959,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index ff8093da80..5a74a6108b 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2859,6 +2859,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index acca32532b..1ad6937047 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2856,6 +2856,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index baa6d23a8e..21e4f5f13b 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -3190,6 +3190,7 @@ GLIBC_2.45 __futex_timedwait_time64 F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 4224217e0c..1877ed350f 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2825,6 +2825,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sys/futex.h b/sysdeps/unix/sysv/linux/sys/futex.h index 2830ae05fa..986869752f 100644 --- a/sysdeps/unix/sysv/linux/sys/futex.h +++ b/sysdeps/unix/sysv/linux/sys/futex.h @@ -29,6 +29,42 @@ # define FUTEX_PRIVATE_FLAG 128 #endif +/* Maximum number of entries in the array passed to futex_waitv. */ +#define FUTEX_WAITV_MAX 128 + +/* Per-waiter flags for futex_waitv, following the kernel definitions + from <linux/futex.h>. FUTEX2_PRIVATE equals FUTEX_PRIVATE_FLAG, so + the same value is used by all futex_* operations. */ +#ifndef FUTEX2_SIZE_U32 +# define FUTEX2_SIZE_U32 0x02 +#endif +#ifndef FUTEX2_PRIVATE +# define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG +#endif +/* With FUTEX2_NUMA the futex word is followed by a second 32-bit word + holding the NUMA node id of the kernel state associated with the + futex; FUTEX_NO_NODE there lets the kernel choose the node. + FUTEX2_MPOL applies the memory policy of the futex word address. */ +#ifndef FUTEX2_NUMA +# define FUTEX2_NUMA 0x04 +#endif +#ifndef FUTEX2_MPOL +# define FUTEX2_MPOL 0x08 +#endif +#ifndef FUTEX_NO_NODE +# define FUTEX_NO_NODE (-1) +#endif + +/* One futex to wait on in a futex_waitv call, with the same layout as + the kernel struct futex_waitv. */ +struct futex_waiter +{ + uint64_t val; /* Expected value of the futex word. */ + uint64_t uaddr; /* Address of the futex word. */ + uint32_t flags; /* FUTEX2_* flags for this futex word. */ + uint32_t __reserved; /* Must be zero. */ +}; + __BEGIN_DECLS /* If *FUTEXP == EXPECTED block until woken by futex_wake (or spuriously). @@ -80,6 +116,20 @@ extern int futex_requeue (uint32_t *__futexp, uint32_t __expected, unsigned int __flags) __THROW __nonnull ((1, 4)); +/* Block on all of the NWAITERS futex words described by WAITERS (at most + FUTEX_WAITV_MAX entries) until woken on any of them or until the absolute + timeout ABSTIME measured against CLOCKID (which must be CLOCK_REALTIME or + CLOCK_MONOTONIC) passes. If ABSTIME is null, block without a timeout. + Each entry checks its own expected value and carries its own FUTEX2_* + flags (FUTEX2_SIZE_U32, optionally with FUTEX2_PRIVATE). */ +#ifdef __USE_TIME_BITS64 +extern int futex_waitv (const struct futex_waiter *__waiters, + unsigned int __nwaiters, unsigned int __flags, + const struct timespec *__abstime, + clockid_t __clockid) + __THROW __nonnull ((1)); +#endif + __END_DECLS #endif /* sys/futex.h */ diff --git a/sysdeps/unix/sysv/linux/tst-futex-consts.py b/sysdeps/unix/sysv/linux/tst-futex-consts.py new file mode 100644 index 0000000000..aef0cf3e1b --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-futex-consts.py @@ -0,0 +1,71 @@ +#!/usr/bin/python3 +# Test that glibc's sys/futex.h constants match the kernel's. +# Copyright (C) 2026 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <https://www.gnu.org/licenses/>. + +import argparse +import sys + +import glibcextract +import glibcsyscalls + + +def main(): + """The main entry point.""" + parser = argparse.ArgumentParser( + description="Test that glibc's sys/futex.h constants " + "match the kernel's.") + parser.add_argument('--cc', metavar='CC', + help='C compiler (including options) to use') + args = parser.parse_args() + + if glibcextract.compile_c_snippet( + '#include <linux/futex.h>', + args.cc).returncode != 0: + sys.exit (77) + + linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) + # Constants in glibc were updated to match Linux v7.1. When glibc + # constants are updated this value should be updated to match the + # released kernel version from which the constants were taken, and + # the futex_waitv per-waiter flags handling should be revisited for + # any new FUTEX2_* flag. + linux_version_glibc = (7, 1) + def check(cte, exclude=None): + return glibcextract.compare_macro_consts( + '#include <sys/futex.h>\n', + '#include <linux/futex.h>\n', + args.cc, + cte, + exclude, + linux_version_glibc > linux_version_headers, + linux_version_headers > linux_version_glibc) + + status = max( + check('FUTEX_WAITV_MAX'), + check('FUTEX_PRIVATE_FLAG'), + check('FUTEX_NO_NODE'), + # glibc only defines the FUTEX2_* flags currently accepted by + # the futex_waitv system call; the sizes other than 32-bit and + # the size mask are not provided. + check('FUTEX2_.*', + 'FUTEX2_SIZE_U8|FUTEX2_SIZE_U16|FUTEX2_SIZE_U64' + '|FUTEX2_SIZE_MASK')) + sys.exit(status) + +if __name__ == '__main__': + main() diff --git a/sysdeps/unix/sysv/linux/tst-futex-waitv-time64.c b/sysdeps/unix/sysv/linux/tst-futex-waitv-time64.c new file mode 100644 index 0000000000..1c1255bf17 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-futex-waitv-time64.c @@ -0,0 +1 @@ +#include "tst-futex-waitv.c" diff --git a/sysdeps/unix/sysv/linux/tst-futex-waitv.c b/sysdeps/unix/sysv/linux/tst-futex-waitv.c new file mode 100644 index 0000000000..9dd14db86e --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-futex-waitv.c @@ -0,0 +1,197 @@ +/* Test for futex_waitv. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <sys/futex.h> +#include <sys/wait.h> +#include <unistd.h> +#include <support/check.h> +#include <support/test-driver.h> + +/* futex_waitv is only declared when time_t is a 64-bit type. */ +#ifdef __USE_TIME_BITS64 + +# include <support/support.h> +# include <support/timespec.h> +# include <support/xthread.h> +# include <support/xtime.h> +# include <support/xunistd.h> + +static uint32_t ftx1; +static uint32_t ftx2; +static int waiter_result; + +static void * +waiter_tf (void *closure) +{ + struct futex_waiter waiters[] = + { + { .val = 0, .uaddr = (uintptr_t) &ftx1, + .flags = FUTEX2_SIZE_U32 | FUTEX2_PRIVATE }, + { .val = 0, .uaddr = (uintptr_t) &ftx2, + .flags = FUTEX2_SIZE_U32 | FUTEX2_PRIVATE }, + }; + int r; + do + r = futex_waitv (waiters, 2, 0, NULL, CLOCK_MONOTONIC); + while (r == -1 && errno == EINTR); + TEST_VERIFY (r >= 0); + __atomic_store_n (&waiter_result, r + 1, __ATOMIC_RELEASE); + return NULL; +} + +static int +do_test_futex_writev (void) +{ + uint32_t word = 5; + struct futex_waiter waiter = + { .val = 4, + .uaddr = (uintptr_t) &word, + .flags = FUTEX2_SIZE_U32 | FUTEX2_PRIVATE + }; + + /* Use a value mismatch to probe for kernel support (Linux 5.16). */ + { + int r = futex_waitv (&waiter, 1, 0, NULL, CLOCK_MONOTONIC); + TEST_COMPARE (r, -1); + if (errno == ENOSYS) + FAIL_UNSUPPORTED ("kernel does not support the futex_waitv syscall"); + TEST_COMPARE (errno, EAGAIN); + } + + /* Nonzero syscall flags are rejected by the kernel. */ + TEST_COMPARE (futex_waitv (&waiter, 1, ~0u, NULL, CLOCK_MONOTONIC), -1); + TEST_COMPARE (errno, EINVAL); + + /* Invalid number of waiters and invalid per-waiter flags. */ + TEST_COMPARE (futex_waitv (&waiter, 0, 0, NULL, CLOCK_MONOTONIC), -1); + TEST_COMPARE (errno, EINVAL); + TEST_COMPARE (futex_waitv (&waiter, FUTEX_WAITV_MAX + 1, 0, NULL, + CLOCK_MONOTONIC), -1); + TEST_COMPARE (errno, EINVAL); + { + struct futex_waiter bad = + { .val = 5, .uaddr = (uintptr_t) &word, .flags = ~0u }; + TEST_COMPARE (futex_waitv (&bad, 1, 0, NULL, CLOCK_MONOTONIC), -1); + TEST_COMPARE (errno, EINVAL); + } + + /* Invalid clock. */ + { + struct timespec ts = make_timespec (0, 0); + waiter.val = 5; + TEST_COMPARE (futex_waitv (&waiter, 1, 0, &ts, CLOCK_PROCESS_CPUTIME_ID), + -1); + TEST_COMPARE (errno, EINVAL); + } + + /* Timeouts in the past, including negative tv_sec. */ + { + struct timespec ts = make_timespec (0, 0); + TEST_COMPARE (futex_waitv (&waiter, 1, 0, &ts, CLOCK_MONOTONIC), -1); + TEST_COMPARE (errno, ETIMEDOUT); + ts = make_timespec (-1, 0); + TEST_COMPARE (futex_waitv (&waiter, 1, 0, &ts, CLOCK_REALTIME), -1); + TEST_COMPARE (errno, ETIMEDOUT); + } + + /* An actual short wait on both supported clocks. */ + for (int i = 0; i < 2; i++) + { + clockid_t clockid = i == 0 ? CLOCK_REALTIME : CLOCK_MONOTONIC; + struct timespec timeout + = timespec_add (xclock_now (clockid), make_timespec (0, 100000000)); + TEST_COMPARE (futex_waitv (&waiter, 1, 0, &timeout, clockid), -1); + TEST_COMPARE (errno, ETIMEDOUT); + TEST_TIMESPEC_NOW_OR_AFTER (clockid, timeout); + } + + /* Block a thread on two futexes and wake it on the second one; the + return value reports the index of the woken futex. */ + { + pthread_t thr = xpthread_create (NULL, waiter_tf, NULL); + + while (__atomic_load_n (&waiter_result, __ATOMIC_ACQUIRE) == 0) + futex_wake (&ftx2, INT_MAX, FUTEX2_PRIVATE); + TEST_COMPARE (__atomic_load_n (&waiter_result, __ATOMIC_ACQUIRE), 1 + 1); + + xpthread_join (thr); + } + + /* The same round-trip with process-shared futexes (no FUTEX2_PRIVATE) + across processes, with the futex words in a shared mapping. */ + { + uint32_t *sftx = support_shared_allocate (3 * sizeof (uint32_t)); + + pid_t pid = xfork (); + if (pid == 0) + { + struct futex_waiter waiters[] = + { + { .val = 0, + .uaddr = (uintptr_t) &sftx[0], + .flags = FUTEX2_SIZE_U32 + }, + { .val = 0, + .uaddr = (uintptr_t) &sftx[1], + .flags = FUTEX2_SIZE_U32 + }, + }; + int r; + do + r = futex_waitv (waiters, 2, 0, NULL, CLOCK_MONOTONIC); + while (r == -1 && errno == EINTR); + if (r < 0) + _exit (2); + __atomic_store_n (&sftx[2], r + 1, __ATOMIC_RELEASE); + _exit (0); + } + + /* Wake the child on the second shared futex. */ + while (__atomic_load_n (&sftx[2], __ATOMIC_ACQUIRE) == 0) + futex_wake (&sftx[1], INT_MAX, 0); + TEST_COMPARE (__atomic_load_n (&sftx[2], __ATOMIC_ACQUIRE), 1 + 1); + + int status; + xwaitpid (pid, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_COMPARE (WEXITSTATUS (status), 0); + + support_shared_free (sftx); + } + + return 0; +} + +#endif + +static int +do_test (void) +{ +#ifdef __USE_TIME_BITS64 + return do_test_futex_writev (); +#else + FAIL_UNSUPPORTED ("futex_waitv is only declared when time_t is a " + "64-bit type (build with -D_TIME_BITS=64)"); +#endif +} + + +#include <support/test-driver.c> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index 8ae243e974..831583c13d 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2774,6 +2774,7 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index c9a00be076..ea5e23cf44 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2793,4 +2793,5 @@ GLIBC_2.43 umaxabs F GLIBC_2.45 futex_requeue F GLIBC_2.45 futex_timedwait F GLIBC_2.45 futex_wait F +GLIBC_2.45 futex_waitv F GLIBC_2.45 futex_wake F