Commit | Line | Data |
---|---|---|
77b4cf5c IK |
1 | #ifndef _ASM_ALPHA_FUTEX_H |
2 | #define _ASM_ALPHA_FUTEX_H | |
4732efbe | 3 | |
77b4cf5c | 4 | #ifdef __KERNEL__ |
4732efbe | 5 | |
77b4cf5c IK |
6 | #include <linux/futex.h> |
7 | #include <linux/uaccess.h> | |
8 | #include <asm/errno.h> | |
9 | #include <asm/barrier.h> | |
10 | ||
11 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | |
12 | __asm__ __volatile__( \ | |
13 | __ASM_SMP_MB \ | |
14 | "1: ldl_l %0,0(%2)\n" \ | |
15 | insn \ | |
16 | "2: stl_c %1,0(%2)\n" \ | |
17 | " beq %1,4f\n" \ | |
18 | " mov $31,%1\n" \ | |
19 | "3: .subsection 2\n" \ | |
20 | "4: br 1b\n" \ | |
21 | " .previous\n" \ | |
22 | " .section __ex_table,\"a\"\n" \ | |
23 | " .long 1b-.\n" \ | |
24 | " lda $31,3b-1b(%1)\n" \ | |
25 | " .long 2b-.\n" \ | |
26 | " lda $31,3b-2b(%1)\n" \ | |
27 | " .previous\n" \ | |
28 | : "=&r" (oldval), "=&r"(ret) \ | |
29 | : "r" (uaddr), "r"(oparg) \ | |
30 | : "memory") | |
31 | ||
81da9f87 JS |
32 | static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, |
33 | u32 __user *uaddr) | |
77b4cf5c | 34 | { |
77b4cf5c | 35 | int oldval = 0, ret; |
77b4cf5c IK |
36 | |
37 | pagefault_disable(); | |
38 | ||
39 | switch (op) { | |
40 | case FUTEX_OP_SET: | |
41 | __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg); | |
42 | break; | |
43 | case FUTEX_OP_ADD: | |
44 | __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
45 | break; | |
46 | case FUTEX_OP_OR: | |
47 | __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
48 | break; | |
49 | case FUTEX_OP_ANDN: | |
50 | __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
51 | break; | |
52 | case FUTEX_OP_XOR: | |
53 | __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg); | |
54 | break; | |
55 | default: | |
56 | ret = -ENOSYS; | |
57 | } | |
58 | ||
59 | pagefault_enable(); | |
60 | ||
81da9f87 JS |
61 | if (!ret) |
62 | *oval = oldval; | |
63 | ||
77b4cf5c IK |
64 | return ret; |
65 | } | |
66 | ||
67 | static inline int | |
8d7718aa ML |
68 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
69 | u32 oldval, u32 newval) | |
77b4cf5c | 70 | { |
8d7718aa ML |
71 | int ret = 0, cmp; |
72 | u32 prev; | |
77b4cf5c | 73 | |
8d7718aa | 74 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
77b4cf5c IK |
75 | return -EFAULT; |
76 | ||
77 | __asm__ __volatile__ ( | |
78 | __ASM_SMP_MB | |
37a9d912 ML |
79 | "1: ldl_l %1,0(%3)\n" |
80 | " cmpeq %1,%4,%2\n" | |
81 | " beq %2,3f\n" | |
82 | " mov %5,%2\n" | |
83 | "2: stl_c %2,0(%3)\n" | |
84 | " beq %2,4f\n" | |
77b4cf5c IK |
85 | "3: .subsection 2\n" |
86 | "4: br 1b\n" | |
87 | " .previous\n" | |
88 | " .section __ex_table,\"a\"\n" | |
89 | " .long 1b-.\n" | |
90 | " lda $31,3b-1b(%0)\n" | |
91 | " .long 2b-.\n" | |
92 | " lda $31,3b-2b(%0)\n" | |
93 | " .previous\n" | |
37a9d912 | 94 | : "+r"(ret), "=&r"(prev), "=&r"(cmp) |
62aca403 | 95 | : "r"(uaddr), "r"((long)(int)oldval), "r"(newval) |
77b4cf5c IK |
96 | : "memory"); |
97 | ||
37a9d912 ML |
98 | *uval = prev; |
99 | return ret; | |
77b4cf5c IK |
100 | } |
101 | ||
102 | #endif /* __KERNEL__ */ | |
103 | #endif /* _ASM_ALPHA_FUTEX_H */ |