mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-18 01:27:40 +00:00

sys_futex_wait() expects a struct __kernel_timespec pointer for the timeout, but the provided struct timespec pointer is of type struct old_timespec32 when compiled for 32-bit architectures, unless they use 64-bit timespecs already. Make it work for all variants by converting the provided timespec value into a local struct __kernel_timespec and provide a pointer to it to the syscall. This is a pointless operation for 64-bit, but this is not a hotpath operation, so keep it simple. This fix is based off [1] Originally-by: Wei Gao <wegao@suse.com> Signed-off-by: Terry Tritton <terry.tritton@linaro.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250704190234.14230-1-terry.tritton@linaro.org Link: https://lore.kernel.org/all/20231203235117.29677-1-wegao@suse.com/ [1]
99 lines
2.0 KiB
C
99 lines
2.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Futex2 library addons for futex tests
|
|
*
|
|
* Copyright 2021 Collabora Ltd.
|
|
*/
|
|
#include <linux/time_types.h>
|
|
#include <stdint.h>
|
|
|
|
#define u64_to_ptr(x) ((void *)(uintptr_t)(x))
|
|
|
|
#ifndef __NR_futex_waitv
|
|
#define __NR_futex_waitv 449
|
|
struct futex_waitv {
|
|
__u64 val;
|
|
__u64 uaddr;
|
|
__u32 flags;
|
|
__u32 __reserved;
|
|
};
|
|
#endif
|
|
|
|
#ifndef __NR_futex_wake
|
|
#define __NR_futex_wake 454
|
|
#endif
|
|
|
|
#ifndef __NR_futex_wait
|
|
#define __NR_futex_wait 455
|
|
#endif
|
|
|
|
#ifndef FUTEX2_SIZE_U32
|
|
#define FUTEX2_SIZE_U32 0x02
|
|
#endif
|
|
|
|
#ifndef FUTEX2_NUMA
|
|
#define FUTEX2_NUMA 0x04
|
|
#endif
|
|
|
|
#ifndef FUTEX2_MPOL
|
|
#define FUTEX2_MPOL 0x08
|
|
#endif
|
|
|
|
#ifndef FUTEX2_PRIVATE
|
|
#define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG
|
|
#endif
|
|
|
|
#ifndef FUTEX2_NO_NODE
|
|
#define FUTEX_NO_NODE (-1)
|
|
#endif
|
|
|
|
#ifndef FUTEX_32
|
|
#define FUTEX_32 FUTEX2_SIZE_U32
|
|
#endif
|
|
|
|
struct futex32_numa {
|
|
futex_t futex;
|
|
futex_t numa;
|
|
};
|
|
|
|
/**
|
|
* futex_waitv - Wait at multiple futexes, wake on any
|
|
* @waiters: Array of waiters
|
|
* @nr_waiters: Length of waiters array
|
|
* @flags: Operation flags
|
|
* @timo: Optional timeout for operation
|
|
*/
|
|
static inline int futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters,
|
|
unsigned long flags, struct timespec *timo, clockid_t clockid)
|
|
{
|
|
struct __kernel_timespec ts = {
|
|
.tv_sec = timo->tv_sec,
|
|
.tv_nsec = timo->tv_nsec,
|
|
};
|
|
|
|
return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, &ts, clockid);
|
|
}
|
|
|
|
/*
|
|
* futex_wait() - block on uaddr with optional timeout
|
|
* @val: Expected value
|
|
* @flags: FUTEX2 flags
|
|
* @timeout: Relative timeout
|
|
* @clockid: Clock id for the timeout
|
|
*/
|
|
static inline int futex2_wait(void *uaddr, long val, unsigned int flags,
|
|
struct timespec *timeout, clockid_t clockid)
|
|
{
|
|
return syscall(__NR_futex_wait, uaddr, val, ~0U, flags, timeout, clockid);
|
|
}
|
|
|
|
/*
|
|
* futex2_wake() - Wake a number of futexes
|
|
* @nr: Number of threads to wake at most
|
|
* @flags: FUTEX2 flags
|
|
*/
|
|
static inline int futex2_wake(void *uaddr, int nr, unsigned int flags)
|
|
{
|
|
return syscall(__NR_futex_wake, uaddr, ~0U, nr, flags);
|
|
}
|