diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2006-06-11 10:25:43 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-06-19 12:39:17 -0400 |
commit | 0307e8d024dffc00743fb54b9afa920a346f1adb (patch) | |
tree | 3e6ea1c677105501fc9efb57105cb23cec4e8f2d /include/asm-mips/futex.h | |
parent | e1701fb2e2f3c02760684e26007e3379be23b690 (diff) |
[MIPS] Fix futex_atomic_op_inuser.
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>
Diffstat (limited to 'include/asm-mips/futex.h')
-rw-r--r-- | include/asm-mips/futex.h | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index 12d118f1bc9..1f94640becc 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h | |||
@@ -22,51 +22,53 @@ | |||
22 | " .set push \n" \ | 22 | " .set push \n" \ |
23 | " .set noat \n" \ | 23 | " .set noat \n" \ |
24 | " .set mips3 \n" \ | 24 | " .set mips3 \n" \ |
25 | "1: ll %1, (%3) # __futex_atomic_op \n" \ | 25 | "1: ll %1, %4 # __futex_atomic_op \n" \ |
26 | " .set mips0 \n" \ | 26 | " .set mips0 \n" \ |
27 | " " insn " \n" \ | 27 | " " insn " \n" \ |
28 | " .set mips3 \n" \ | 28 | " .set mips3 \n" \ |
29 | "2: sc $1, (%3) \n" \ | 29 | "2: sc $1, %2 \n" \ |
30 | " beqzl $1, 1b \n" \ | 30 | " beqzl $1, 1b \n" \ |
31 | __FUTEX_SMP_SYNC \ | 31 | __FUTEX_SMP_SYNC \ |
32 | "3: \n" \ | 32 | "3: \n" \ |
33 | " .set pop \n" \ | 33 | " .set pop \n" \ |
34 | " .set mips0 \n" \ | 34 | " .set mips0 \n" \ |
35 | " .section .fixup,\"ax\" \n" \ | 35 | " .section .fixup,\"ax\" \n" \ |
36 | "4: li %0, %5 \n" \ | 36 | "4: li %0, %6 \n" \ |
37 | " j 2b \n" \ | 37 | " j 2b \n" \ |
38 | " .previous \n" \ | 38 | " .previous \n" \ |
39 | " .section __ex_table,\"a\" \n" \ | 39 | " .section __ex_table,\"a\" \n" \ |
40 | " "__UA_ADDR "\t1b, 4b \n" \ | 40 | " "__UA_ADDR "\t1b, 4b \n" \ |
41 | " "__UA_ADDR "\t2b, 4b \n" \ | 41 | " "__UA_ADDR "\t2b, 4b \n" \ |
42 | " .previous \n" \ | 42 | " .previous \n" \ |
43 | : "=r" (ret), "=r" (oldval) \ | 43 | : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ |
44 | : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ | 44 | : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ |
45 | : "memory"); \ | ||
45 | } else if (cpu_has_llsc) { \ | 46 | } else if (cpu_has_llsc) { \ |
46 | __asm__ __volatile__( \ | 47 | __asm__ __volatile__( \ |
47 | " .set push \n" \ | 48 | " .set push \n" \ |
48 | " .set noat \n" \ | 49 | " .set noat \n" \ |
49 | " .set mips3 \n" \ | 50 | " .set mips3 \n" \ |
50 | "1: ll %1, (%3) # __futex_atomic_op \n" \ | 51 | "1: ll %1, %4 # __futex_atomic_op \n" \ |
51 | " .set mips0 \n" \ | 52 | " .set mips0 \n" \ |
52 | " " insn " \n" \ | 53 | " " insn " \n" \ |
53 | " .set mips3 \n" \ | 54 | " .set mips3 \n" \ |
54 | "2: sc $1, (%3) \n" \ | 55 | "2: sc $1, %2 \n" \ |
55 | " beqz $1, 1b \n" \ | 56 | " beqz $1, 1b \n" \ |
56 | __FUTEX_SMP_SYNC \ | 57 | __FUTEX_SMP_SYNC \ |
57 | "3: \n" \ | 58 | "3: \n" \ |
58 | " .set pop \n" \ | 59 | " .set pop \n" \ |
59 | " .set mips0 \n" \ | 60 | " .set mips0 \n" \ |
60 | " .section .fixup,\"ax\" \n" \ | 61 | " .section .fixup,\"ax\" \n" \ |
61 | "4: li %0, %5 \n" \ | 62 | "4: li %0, %6 \n" \ |
62 | " j 2b \n" \ | 63 | " j 2b \n" \ |
63 | " .previous \n" \ | 64 | " .previous \n" \ |
64 | " .section __ex_table,\"a\" \n" \ | 65 | " .section __ex_table,\"a\" \n" \ |
65 | " "__UA_ADDR "\t1b, 4b \n" \ | 66 | " "__UA_ADDR "\t1b, 4b \n" \ |
66 | " "__UA_ADDR "\t2b, 4b \n" \ | 67 | " "__UA_ADDR "\t2b, 4b \n" \ |
67 | " .previous \n" \ | 68 | " .previous \n" \ |
68 | : "=r" (ret), "=r" (oldval) \ | 69 | : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ |
69 | : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ | 70 | : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ |
71 | : "memory"); \ | ||
70 | } else \ | 72 | } else \ |
71 | ret = -ENOSYS; \ | 73 | ret = -ENOSYS; \ |
72 | } | 74 | } |
@@ -89,23 +91,23 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
89 | 91 | ||
90 | switch (op) { | 92 | switch (op) { |
91 | case FUTEX_OP_SET: | 93 | case FUTEX_OP_SET: |
92 | __futex_atomic_op("move $1, %z4", ret, oldval, uaddr, oparg); | 94 | __futex_atomic_op("move $1, %z5", ret, oldval, uaddr, oparg); |
93 | break; | 95 | break; |
94 | 96 | ||
95 | case FUTEX_OP_ADD: | 97 | case FUTEX_OP_ADD: |
96 | __futex_atomic_op("addu $1, %1, %z4", | 98 | __futex_atomic_op("addu $1, %1, %z5", |
97 | ret, oldval, uaddr, oparg); | 99 | ret, oldval, uaddr, oparg); |
98 | break; | 100 | break; |
99 | case FUTEX_OP_OR: | 101 | case FUTEX_OP_OR: |
100 | __futex_atomic_op("or $1, %1, %z4", | 102 | __futex_atomic_op("or $1, %1, %z5", |
101 | ret, oldval, uaddr, oparg); | 103 | ret, oldval, uaddr, oparg); |
102 | break; | 104 | break; |
103 | case FUTEX_OP_ANDN: | 105 | case FUTEX_OP_ANDN: |
104 | __futex_atomic_op("and $1, %1, %z4", | 106 | __futex_atomic_op("and $1, %1, %z5", |
105 | ret, oldval, uaddr, ~oparg); | 107 | ret, oldval, uaddr, ~oparg); |
106 | break; | 108 | break; |
107 | case FUTEX_OP_XOR: | 109 | case FUTEX_OP_XOR: |
108 | __futex_atomic_op("xor $1, %1, %z4", | 110 | __futex_atomic_op("xor $1, %1, %z5", |
109 | ret, oldval, uaddr, oparg); | 111 | ret, oldval, uaddr, oparg); |
110 | break; | 112 | break; |
111 | default: | 113 | default: |