aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2006-06-11 10:25:43 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-06-19 12:39:17 -0400
commit0307e8d024dffc00743fb54b9afa920a346f1adb (patch)
tree3e6ea1c677105501fc9efb57105cb23cec4e8f2d
parente1701fb2e2f3c02760684e26007e3379be23b690 (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>
-rw-r--r--include/asm-mips/futex.h32
1 files changed, 17 insertions, 15 deletions
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 12d118f1bc9c..1f94640becc4 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: