summaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/syscall.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index af3a605fc4..17e17f4804 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7773,11 +7773,11 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
int op, int val, target_ulong timeout,
target_ulong uaddr2, int val3)
{
- struct timespec ts, *pts;
+ struct timespec ts, *pts = NULL;
+ void *haddr2 = NULL;
int base_op;
- /* ??? We assume FUTEX_* constants are the same on both host
- and target. */
+ /* We assume FUTEX_* constants are the same on both host and target. */
#ifdef FUTEX_CMD_MASK
base_op = op & FUTEX_CMD_MASK;
#else
@@ -7786,39 +7786,41 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
switch (base_op) {
case FUTEX_WAIT:
case FUTEX_WAIT_BITSET:
- if (timeout) {
- pts = &ts;
- if (time64
- ? target_to_host_timespec64(pts, timeout)
- : target_to_host_timespec(pts, timeout)) {
- return -TARGET_EFAULT;
- }
- } else {
- pts = NULL;
- }
- return do_safe_futex(g2h(cpu, uaddr),
- op, tswap32(val), pts, NULL, val3);
+ val = tswap32(val);
+ break;
case FUTEX_WAKE:
- return do_safe_futex(g2h(cpu, uaddr),
- op, val, NULL, NULL, 0);
+ timeout = 0;
+ break;
case FUTEX_FD:
- return do_safe_futex(g2h(cpu, uaddr),
- op, val, NULL, NULL, 0);
- case FUTEX_REQUEUE:
+ timeout = 0;
+ break;
case FUTEX_CMP_REQUEUE:
+ val3 = tswap32(val3);
+ /* fall through */
+ case FUTEX_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));
+ /*
+ * For these, the 4th argument is not TIMEOUT, but VAL2.
+ * But the prototype of do_safe_futex takes a pointer, so
+ * insert casts to satisfy the compiler. We do not need
+ * to tswap VAL2 since it's not compared to guest memory.
+ */
+ pts = (struct timespec *)(uintptr_t)timeout;
+ timeout = 0;
+ haddr2 = g2h(cpu, uaddr2);
+ break;
default:
return -TARGET_ENOSYS;
}
+ if (timeout) {
+ pts = &ts;
+ if (time64
+ ? target_to_host_timespec64(pts, timeout)
+ : target_to_host_timespec(pts, timeout)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
}
#endif