Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/csky/include/asm/futex.h
26493 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
3
#ifndef __ASM_CSKY_FUTEX_H
4
#define __ASM_CSKY_FUTEX_H
5
6
#ifndef CONFIG_SMP
7
#include <asm-generic/futex.h>
8
#else
9
#include <linux/atomic.h>
10
#include <linux/futex.h>
11
#include <linux/uaccess.h>
12
#include <linux/errno.h>
13
14
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
15
{ \
16
u32 tmp; \
17
\
18
__atomic_pre_full_fence(); \
19
\
20
__asm__ __volatile__ ( \
21
"1: ldex.w %[ov], %[u] \n" \
22
" "insn" \n" \
23
"2: stex.w %[t], %[u] \n" \
24
" bez %[t], 1b \n" \
25
" br 4f \n" \
26
"3: mov %[r], %[e] \n" \
27
"4: \n" \
28
" .section __ex_table,\"a\" \n" \
29
" .balign 4 \n" \
30
" .long 1b, 3b \n" \
31
" .long 2b, 3b \n" \
32
" .previous \n" \
33
: [r] "+r" (ret), [ov] "=&r" (oldval), \
34
[u] "+m" (*uaddr), [t] "=&r" (tmp) \
35
: [op] "Jr" (oparg), [e] "jr" (-EFAULT) \
36
: "memory"); \
37
\
38
__atomic_post_full_fence(); \
39
}
40
41
static inline int
42
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
43
{
44
int oldval = 0, ret = 0;
45
46
if (!access_ok(uaddr, sizeof(u32)))
47
return -EFAULT;
48
49
switch (op) {
50
case FUTEX_OP_SET:
51
__futex_atomic_op("mov %[t], %[ov]",
52
ret, oldval, uaddr, oparg);
53
break;
54
case FUTEX_OP_ADD:
55
__futex_atomic_op("add %[t], %[ov], %[op]",
56
ret, oldval, uaddr, oparg);
57
break;
58
case FUTEX_OP_OR:
59
__futex_atomic_op("or %[t], %[ov], %[op]",
60
ret, oldval, uaddr, oparg);
61
break;
62
case FUTEX_OP_ANDN:
63
__futex_atomic_op("and %[t], %[ov], %[op]",
64
ret, oldval, uaddr, ~oparg);
65
break;
66
case FUTEX_OP_XOR:
67
__futex_atomic_op("xor %[t], %[ov], %[op]",
68
ret, oldval, uaddr, oparg);
69
break;
70
default:
71
ret = -ENOSYS;
72
}
73
74
if (!ret)
75
*oval = oldval;
76
77
return ret;
78
}
79
80
81
82
static inline int
83
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
84
u32 oldval, u32 newval)
85
{
86
int ret = 0;
87
u32 val, tmp;
88
89
if (!access_ok(uaddr, sizeof(u32)))
90
return -EFAULT;
91
92
__atomic_pre_full_fence();
93
94
__asm__ __volatile__ (
95
"1: ldex.w %[v], %[u] \n"
96
" cmpne %[v], %[ov] \n"
97
" bt 4f \n"
98
" mov %[t], %[nv] \n"
99
"2: stex.w %[t], %[u] \n"
100
" bez %[t], 1b \n"
101
" br 4f \n"
102
"3: mov %[r], %[e] \n"
103
"4: \n"
104
" .section __ex_table,\"a\" \n"
105
" .balign 4 \n"
106
" .long 1b, 3b \n"
107
" .long 2b, 3b \n"
108
" .previous \n"
109
: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr),
110
[t] "=&r" (tmp)
111
: [ov] "Jr" (oldval), [nv] "Jr" (newval), [e] "Jr" (-EFAULT)
112
: "memory");
113
114
__atomic_post_full_fence();
115
116
*uval = val;
117
return ret;
118
}
119
120
#endif /* CONFIG_SMP */
121
#endif /* __ASM_CSKY_FUTEX_H */
122
123