Patchwork [7/7] linux-user: make FUTEX_* calls honor timeout parameter

login
register
mail settings
Submitter Nathan Froyd
Date Aug. 3, 2009, 3:43 p.m.
Message ID <1249314209-10230-8-git-send-email-froydnj@codesourcery.com>
Download mbox | patch
Permalink /patch/30649/
State Superseded
Headers show

Comments

Nathan Froyd - Aug. 3, 2009, 3:43 p.m.
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
---
 linux-user/syscall.c |   24 ++++++++++++++++--------
 1 files changed, 16 insertions(+), 8 deletions(-)

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b5f669e..673eed4 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;
     }