diff options
author | Nathan Froyd <froydnj@codesourcery.com> | 2009-08-03 08:43:29 -0700 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2009-08-03 20:33:42 +0400 |
commit | a16aae0ca427f117c51d80e5d72e18b141595496 (patch) | |
tree | 60760c9de11498ee81ac92be27303ff3b6db049c | |
parent | d6630708bdc8665d96d35e22931463c85004a808 (diff) | |
download | qemu-a16aae0ca427f117c51d80e5d72e18b141595496.tar.gz qemu-a16aae0ca427f117c51d80e5d72e18b141595496.tar.bz2 qemu-a16aae0ca427f117c51d80e5d72e18b141595496.zip |
linux-user: make FUTEX_* calls honor timeout parameter
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: malc <av1474@comtv.ru>
-rw-r--r-- | linux-user/syscall.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b5f669e282..673eed4ece 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4026,14 +4026,16 @@ static int do_futex(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 - switch ((op&FUTEX_CMD_MASK)) { + base_op = op & FUTEX_CMD_MASK; #else - switch (op) { + base_op = op; #endif + switch (base_op) { case FUTEX_WAIT: if (timeout) { pts = &ts; @@ -4045,16 +4047,22 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, pts, NULL, 0)); case FUTEX_WAKE: return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); - case FUTEX_WAKE_OP: - return get_errno(sys_futex(g2h(uaddr), op, val, NULL, g2h(uaddr2), val3 )); case FUTEX_FD: return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); case FUTEX_REQUEUE: - return get_errno(sys_futex(g2h(uaddr), op, val, - NULL, g2h(uaddr2), 0)); case FUTEX_CMP_REQUEUE: - return get_errno(sys_futex(g2h(uaddr), op, val, - NULL, g2h(uaddr2), tswap32(val3))); + 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 get_errno(sys_futex(g2h(uaddr), op, val, pts, + g2h(uaddr2), + (base_op == FUTEX_CMP_REQUEUE + ? tswap32(val3) + : val3))); default: return -TARGET_ENOSYS; } |