linux-user: Combine do_futex and do_futex_time64

Pass a boolean to select between time32 and time64.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20220829021006.67305-2-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Richard Henderson 2022-08-28 19:09:59 -07:00 committed by Laurent Vivier
parent fbf47c18aa
commit 0fbc0f8da1

View File

@ -7768,9 +7768,10 @@ static int do_safe_futex(int *uaddr, int op, int val,
futexes locally would make futexes shared between multiple processes futexes locally would make futexes shared between multiple processes
tricky. However they're probably useless because guest atomic tricky. However they're probably useless because guest atomic
operations won't work either. */ operations won't work either. */
#if defined(TARGET_NR_futex) #if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val, static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
target_ulong timeout, target_ulong uaddr2, int val3) int op, int val, target_ulong timeout,
target_ulong uaddr2, int val3)
{ {
struct timespec ts, *pts; struct timespec ts, *pts;
int base_op; int base_op;
@ -7787,7 +7788,11 @@ static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
case FUTEX_WAIT_BITSET: case FUTEX_WAIT_BITSET:
if (timeout) { if (timeout) {
pts = &ts; pts = &ts;
target_to_host_timespec(pts, timeout); if (time64
? target_to_host_timespec64(pts, timeout)
: target_to_host_timespec(pts, timeout)) {
return -TARGET_EFAULT;
}
} else { } else {
pts = NULL; pts = NULL;
} }
@ -7817,56 +7822,6 @@ static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
} }
#endif #endif
#if defined(TARGET_NR_futex_time64)
static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
int val, target_ulong timeout,
target_ulong uaddr2, int val3)
{
struct timespec ts, *pts;
int base_op;
/* ??? We assume FUTEX_* constants are the same on both host
and target. */
#ifdef FUTEX_CMD_MASK
base_op = op & FUTEX_CMD_MASK;
#else
base_op = op;
#endif
switch (base_op) {
case FUTEX_WAIT:
case FUTEX_WAIT_BITSET:
if (timeout) {
pts = &ts;
if (target_to_host_timespec64(pts, timeout)) {
return -TARGET_EFAULT;
}
} else {
pts = NULL;
}
return do_safe_futex(g2h(cpu, uaddr), op,
tswap32(val), pts, NULL, val3);
case FUTEX_WAKE:
return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
case FUTEX_FD:
return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
case FUTEX_REQUEUE:
case FUTEX_CMP_REQUEUE:
case FUTEX_WAKE_OP:
/* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
TIMEOUT parameter is interpreted as a uint32_t by the kernel.
But the prototype takes a `struct timespec *'; insert casts
to satisfy the compiler. We do not need to tswap TIMEOUT
since it's not compared to guest memory. */
pts = (struct timespec *)(uintptr_t) timeout;
return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
(base_op == FUTEX_CMP_REQUEUE
? tswap32(val3) : val3));
default:
return -TARGET_ENOSYS;
}
}
#endif
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
abi_long handle, abi_long mount_id, abi_long handle, abi_long mount_id,
@ -12372,11 +12327,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif #endif
#ifdef TARGET_NR_futex #ifdef TARGET_NR_futex
case TARGET_NR_futex: case TARGET_NR_futex:
return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6); return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
#endif #endif
#ifdef TARGET_NR_futex_time64 #ifdef TARGET_NR_futex_time64
case TARGET_NR_futex_time64: case TARGET_NR_futex_time64:
return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6); return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
#endif #endif
#ifdef CONFIG_INOTIFY #ifdef CONFIG_INOTIFY
#if defined(TARGET_NR_inotify_init) #if defined(TARGET_NR_inotify_init)