linux-mips
[Top] [All Lists]

Re: [PATCH] fix futex_atomic_op_inuser

To: linux-mips@linux-mips.org
Subject: Re: [PATCH] fix futex_atomic_op_inuser
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Sun, 11 Jun 2006 23:30:01 +0900 (JST)
Cc: ralf@linux-mips.org
In-reply-to: <20060611.232543.59465208.anemo@mba.ocn.ne.jp>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <20060611.232543.59465208.anemo@mba.ocn.ne.jp>
Sender: linux-mips-bounce@linux-mips.org
On Sun, 11 Jun 2006 23:25:43 +0900 (JST), Atsushi Nemoto <anemo@mba.ocn.ne.jp> 
wrote:
> 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.
> 
> This patch solved the problem.

And here is a patch for 2.6.16-stable tree.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>

diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 2454c44..e1f960d 100644
--- a/include/asm-mips/futex.h
+++ b/include/asm-mips/futex.h
@@ -20,26 +20,27 @@
        "       .set    push                                    \n"     \
        "       .set    noat                                    \n"     \
        "       .set    mips3                                   \n"     \
-       "1:     ll      %1, (%3)        # __futex_atomic_op1    \n"     \
+       "1:     ll      %1, %4  # __futex_atomic_op1            \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");                                                    \
 }
 
 static inline int
@@ -60,23 +61,23 @@ futex_atomic_op_inuser (int encoded_op, 
 
        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:

<Prev in Thread] Current Thread [Next in Thread>