[MIPS] Fix futex_atomic_op_inuser.
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Sun, 11 Jun 2006 14:25:43 +0000 (23:25 +0900)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 19 Jun 2006 16:39:17 +0000 (17:39 +0100)
I found that NPTL's pthread_cond_signal() does not work properly on
kernels compiled by gcc 4.1.x.  I suppose inline asm for
__futex_atomic_op() was wrong.  I suppose:

1. "=&r" constraint should be used for oldval.
2. Instead of "r" (uaddr), "=R" (*uaddr) for output and "R" (*uaddr)
   for input should be used.
3. "memory" should be added to the clobber list.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
include/asm-mips/futex.h

index 12d118f1bc9c7768d3a2e14b9ed0458e5569feb6..1f94640becc48a6b1868f42e214efb7e4b6c8306 100644 (file)
                "       .set    push                            \n"     \
                "       .set    noat                            \n"     \
                "       .set    mips3                           \n"     \
-               "1:     ll      %1, (%3)        # __futex_atomic_op     \n" \
+               "1:     ll      %1, %4  # __futex_atomic_op     \n"     \
                "       .set    mips0                           \n"     \
                "       " insn  "                               \n"     \
                "       .set    mips3                           \n"     \
-               "2:     sc      $1, (%3)                        \n"     \
+               "2:     sc      $1, %2                          \n"     \
                "       beqzl   $1, 1b                          \n"     \
                __FUTEX_SMP_SYNC                                        \
                "3:                                             \n"     \
                "       .set    pop                             \n"     \
                "       .set    mips0                           \n"     \
                "       .section .fixup,\"ax\"                  \n"     \
-               "4:     li      %0, %5                          \n"     \
+               "4:     li      %0, %6                          \n"     \
                "       j       2b                              \n"     \
                "       .previous                               \n"     \
                "       .section __ex_table,\"a\"               \n"     \
                "       "__UA_ADDR "\t1b, 4b                    \n"     \
                "       "__UA_ADDR "\t2b, 4b                    \n"     \
                "       .previous                               \n"     \
-               : "=r" (ret), "=r" (oldval)                             \
-               : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));   \
+               : "=r" (ret), "=&r" (oldval), "=R" (*uaddr)             \
+               : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)    \
+               : "memory");                                            \
        } else if (cpu_has_llsc) {                                      \
                __asm__ __volatile__(                                   \
                "       .set    push                            \n"     \
                "       .set    noat                            \n"     \
                "       .set    mips3                           \n"     \
-               "1:     ll      %1, (%3)        # __futex_atomic_op     \n" \
+               "1:     ll      %1, %4  # __futex_atomic_op     \n"     \
                "       .set    mips0                           \n"     \
                "       " insn  "                               \n"     \
                "       .set    mips3                           \n"     \
-               "2:     sc      $1, (%3)                        \n"     \
+               "2:     sc      $1, %2                          \n"     \
                "       beqz    $1, 1b                          \n"     \
                __FUTEX_SMP_SYNC                                        \
                "3:                                             \n"     \
                "       .set    pop                             \n"     \
                "       .set    mips0                           \n"     \
                "       .section .fixup,\"ax\"                  \n"     \
-               "4:     li      %0, %5                          \n"     \
+               "4:     li      %0, %6                          \n"     \
                "       j       2b                              \n"     \
                "       .previous                               \n"     \
                "       .section __ex_table,\"a\"               \n"     \
                "       "__UA_ADDR "\t1b, 4b                    \n"     \
                "       "__UA_ADDR "\t2b, 4b                    \n"     \
                "       .previous                               \n"     \
-               : "=r" (ret), "=r" (oldval)                             \
-               : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));   \
+               : "=r" (ret), "=&r" (oldval), "=R" (*uaddr)             \
+               : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)    \
+               : "memory");                                            \
        } else                                                          \
                ret = -ENOSYS;                                          \
 }
@@ -89,23 +91,23 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
        switch (op) {
        case FUTEX_OP_SET:
-               __futex_atomic_op("move $1, %z4", ret, oldval, uaddr, oparg);
+               __futex_atomic_op("move $1, %z5", ret, oldval, uaddr, oparg);
                break;
 
        case FUTEX_OP_ADD:
-               __futex_atomic_op("addu $1, %1, %z4",
+               __futex_atomic_op("addu $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        case FUTEX_OP_OR:
-               __futex_atomic_op("or   $1, %1, %z4",
+               __futex_atomic_op("or   $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        case FUTEX_OP_ANDN:
-               __futex_atomic_op("and  $1, %1, %z4",
+               __futex_atomic_op("and  $1, %1, %z5",
                                  ret, oldval, uaddr, ~oparg);
                break;
        case FUTEX_OP_XOR:
-               __futex_atomic_op("xor  $1, %1, %z4",
+               __futex_atomic_op("xor  $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        default: