diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-09-15 04:52:34 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:32:21 -0400 |
commit | ebfaebae364c3631c70467bf89a63b341d0f0949 (patch) | |
tree | 837833970842137f0ca9a4992e30a30a12cde241 | |
parent | 9dbdfce85c165faa45509ca3b18deaa5f9dfbc12 (diff) |
Futexes for MIPS, for the time being only the R10000_LLSC_WAR version.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | include/asm-mips/futex.h | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index 9feff4ce1424..2454c44a8f54 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h | |||
@@ -3,10 +3,45 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <linux/config.h> | ||
6 | #include <linux/futex.h> | 7 | #include <linux/futex.h> |
7 | #include <asm/errno.h> | 8 | #include <asm/errno.h> |
8 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
9 | 10 | ||
11 | #ifdef CONFIG_SMP | ||
12 | #define __FUTEX_SMP_SYNC " sync \n" | ||
13 | #else | ||
14 | #define __FUTEX_SMP_SYNC | ||
15 | #endif | ||
16 | |||
17 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | ||
18 | { \ | ||
19 | __asm__ __volatile__( \ | ||
20 | " .set push \n" \ | ||
21 | " .set noat \n" \ | ||
22 | " .set mips3 \n" \ | ||
23 | "1: ll %1, (%3) # __futex_atomic_op1 \n" \ | ||
24 | " .set mips0 \n" \ | ||
25 | " " insn " \n" \ | ||
26 | " .set mips3 \n" \ | ||
27 | "2: sc $1, (%3) \n" \ | ||
28 | " beqzl $1, 1b \n" \ | ||
29 | __FUTEX_SMP_SYNC \ | ||
30 | "3: \n" \ | ||
31 | " .set pop \n" \ | ||
32 | " .set mips0 \n" \ | ||
33 | " .section .fixup,\"ax\" \n" \ | ||
34 | "4: li %0, %5 \n" \ | ||
35 | " j 2b \n" \ | ||
36 | " .previous \n" \ | ||
37 | " .section __ex_table,\"a\" \n" \ | ||
38 | " "__UA_ADDR "\t1b, 4b \n" \ | ||
39 | " "__UA_ADDR "\t2b, 4b \n" \ | ||
40 | " .previous \n" \ | ||
41 | : "=r" (ret), "=r" (oldval) \ | ||
42 | : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ | ||
43 | } | ||
44 | |||
10 | static inline int | 45 | static inline int |
11 | futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | 46 | futex_atomic_op_inuser (int encoded_op, int __user *uaddr) |
12 | { | 47 | { |
@@ -25,10 +60,25 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
25 | 60 | ||
26 | switch (op) { | 61 | switch (op) { |
27 | case FUTEX_OP_SET: | 62 | case FUTEX_OP_SET: |
63 | __futex_atomic_op("move $1, %z4", ret, oldval, uaddr, oparg); | ||
64 | break; | ||
65 | |||
28 | case FUTEX_OP_ADD: | 66 | case FUTEX_OP_ADD: |
67 | __futex_atomic_op("addu $1, %1, %z4", | ||
68 | ret, oldval, uaddr, oparg); | ||
69 | break; | ||
29 | case FUTEX_OP_OR: | 70 | case FUTEX_OP_OR: |
71 | __futex_atomic_op("or $1, %1, %z4", | ||
72 | ret, oldval, uaddr, oparg); | ||
73 | break; | ||
30 | case FUTEX_OP_ANDN: | 74 | case FUTEX_OP_ANDN: |
75 | __futex_atomic_op("and $1, %1, %z4", | ||
76 | ret, oldval, uaddr, ~oparg); | ||
77 | break; | ||
31 | case FUTEX_OP_XOR: | 78 | case FUTEX_OP_XOR: |
79 | __futex_atomic_op("xor $1, %1, %z4", | ||
80 | ret, oldval, uaddr, oparg); | ||
81 | break; | ||
32 | default: | 82 | default: |
33 | ret = -ENOSYS; | 83 | ret = -ENOSYS; |
34 | } | 84 | } |