Skip to content

Commit 825b43e

Browse files
committed
ARCv3: add implementation for futex atomic with atld.<op>
As standard implementation of futex atomics through llock/scond instructions can't be use for all CPUs, add new implementation with atld.<op> instructions which can be used if ARC_HAS_ATLD enabled. Signed-off-by: Pavel Kozlov <pavel.kozlov@synopsys.com>
1 parent bc57bd4 commit 825b43e

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

arch/arc/include/asm/futex.h

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,33 @@
1515
#include <asm/assembler.h>
1616
#include <asm/errno.h>
1717

18-
#ifdef CONFIG_ARC_HAS_LLSC
18+
#ifdef CONFIG_ARC_HAS_ATLD
19+
20+
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
21+
\
22+
smp_mb(); \
23+
__asm__ __volatile__( \
24+
" mov %1, %3 \n" \
25+
"1: \n" \
26+
insn "\n" \
27+
" mov %0, 0 \n" \
28+
"2: \n" \
29+
" .section .fixup,\"ax\" \n" \
30+
" .align 4 \n" \
31+
"3: mov %0, %4 \n" \
32+
" b 2b \n" \
33+
" .previous \n" \
34+
" .section __ex_table,\"a\" \n" \
35+
" .align " REGSZASM " \n" \
36+
" " ARC_PTR " 1b, 3b \n" \
37+
" .previous \n" \
38+
\
39+
: "=&r" (ret), "=&r" (oldval) \
40+
: "r" (uaddr), "r" (oparg), "ir" (-EFAULT) \
41+
: "cc", "memory"); \
42+
smp_mb() \
43+
44+
#elif defined(CONFIG_ARC_HAS_LLSC)
1945

2046
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
2147
\
@@ -72,6 +98,22 @@
7298

7399
#endif
74100

101+
#ifdef CONFIG_ARC_HAS_ATLD
102+
#define ARC_OP_SET "ex %1, [%2]"
103+
#define ARC_OP_ADD "atld.add %1, [%2]"
104+
#define ARC_OP_OR "atld.or %1, [%2]"
105+
#define ARC_OP_ANDN "atld.and %1, [%2]"
106+
#define ARC_OP_XOR "atld.xor %1, [%2]"
107+
#define ARC_OPARG_ANDN ~oparg
108+
#else /* !CONFIG_ARC_HAS_ATLD */
109+
#define ARC_OP_SET "mov %0, %3"
110+
#define ARC_OP_ADD "add %0, %1, %3"
111+
#define ARC_OP_OR "or %0, %1, %3"
112+
#define ARC_OP_ANDN "bic %0, %1, %3"
113+
#define ARC_OP_XOR "xor %0, %1, %3"
114+
#define ARC_OPARG_ANDN oparg
115+
#endif
116+
75117
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
76118
u32 __user *uaddr)
77119
{
@@ -80,32 +122,32 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
80122
if (!access_ok(uaddr, sizeof(u32)))
81123
return -EFAULT;
82124

83-
#ifndef CONFIG_ARC_HAS_LLSC
125+
#if !defined(CONFIG_ARC_HAS_LLSC) && !defined(CONFIG_ARC_HAS_ATLD)
84126
preempt_disable(); /* to guarantee atomic r-m-w of futex op */
85127
#endif
86128

87129
switch (op) {
88130
case FUTEX_OP_SET:
89-
__futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
131+
__futex_atomic_op(ARC_OP_SET, ret, oldval, uaddr, oparg);
90132
break;
91133
case FUTEX_OP_ADD:
92134
/* oldval = *uaddr; *uaddr += oparg ; ret = *uaddr */
93-
__futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
135+
__futex_atomic_op(ARC_OP_ADD, ret, oldval, uaddr, oparg);
94136
break;
95137
case FUTEX_OP_OR:
96-
__futex_atomic_op("or %0, %1, %3", ret, oldval, uaddr, oparg);
138+
__futex_atomic_op(ARC_OP_OR, ret, oldval, uaddr, oparg);
97139
break;
98140
case FUTEX_OP_ANDN:
99-
__futex_atomic_op("bic %0, %1, %3", ret, oldval, uaddr, oparg);
141+
__futex_atomic_op(ARC_OP_ANDN, ret, oldval, uaddr, ARC_OPARG_ANDN);
100142
break;
101143
case FUTEX_OP_XOR:
102-
__futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg);
144+
__futex_atomic_op(ARC_OP_XOR, ret, oldval, uaddr, oparg);
103145
break;
104146
default:
105147
ret = -ENOSYS;
106148
}
107149

108-
#ifndef CONFIG_ARC_HAS_LLSC
150+
#if !defined(CONFIG_ARC_HAS_LLSC) && !defined(CONFIG_ARC_HAS_ATLD)
109151
preempt_enable();
110152
#endif
111153

0 commit comments

Comments
 (0)