aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-09-15 04:52:34 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:32:21 -0400
commitebfaebae364c3631c70467bf89a63b341d0f0949 (patch)
tree837833970842137f0ca9a4992e30a30a12cde241 /include/asm-mips
parent9dbdfce85c165faa45509ca3b18deaa5f9dfbc12 (diff)
Futexes for MIPS, for the time being only the R10000_LLSC_WAR version.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips')
-rw-r--r--include/asm-mips/futex.h50
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
10static inline int 45static inline int
11futex_atomic_op_inuser (int encoded_op, int __user *uaddr) 46futex_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 }