summary refs log tree commit diff stats
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorNathan Froyd <froydnj@codesourcery.com>2009-08-03 08:43:29 -0700
committermalc <av1474@comtv.ru>2009-08-03 20:33:42 +0400
commita16aae0ca427f117c51d80e5d72e18b141595496 (patch)
tree60760c9de11498ee81ac92be27303ff3b6db049c /linux-user/syscall.c
parentd6630708bdc8665d96d35e22931463c85004a808 (diff)
downloadfocaccia-qemu-a16aae0ca427f117c51d80e5d72e18b141595496.tar.gz
focaccia-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>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c24
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;
     }