ARC: atomic: !LLSC: use int data type consistently
[linux-2.6-microblaze.git] / arch / arc / include / asm / atomic-spinlock.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef _ASM_ARC_ATOMIC_SPLOCK_H
4 #define _ASM_ARC_ATOMIC_SPLOCK_H
5
6 /*
7  * Non hardware assisted Atomic-R-M-W
8  * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
9  */
10
11 static inline void arch_atomic_set(atomic_t *v, int i)
12 {
13         /*
14          * Independent of hardware support, all of the atomic_xxx() APIs need
15          * to follow the same locking rules to make sure that a "hardware"
16          * atomic insn (e.g. LD) doesn't clobber an "emulated" atomic insn
17          * sequence
18          *
19          * Thus atomic_set() despite being 1 insn (and seemingly atomic)
20          * requires the locking.
21          */
22         unsigned long flags;
23
24         atomic_ops_lock(flags);
25         WRITE_ONCE(v->counter, i);
26         atomic_ops_unlock(flags);
27 }
28
29 #define arch_atomic_set_release(v, i)   arch_atomic_set((v), (i))
30
31 #define ATOMIC_OP(op, c_op, asm_op)                                     \
32 static inline void arch_atomic_##op(int i, atomic_t *v)                 \
33 {                                                                       \
34         unsigned long flags;                                            \
35                                                                         \
36         atomic_ops_lock(flags);                                         \
37         v->counter c_op i;                                              \
38         atomic_ops_unlock(flags);                                       \
39 }
40
41 #define ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
42 static inline int arch_atomic_##op##_return(int i, atomic_t *v)         \
43 {                                                                       \
44         unsigned long flags;                                            \
45         unsigned int temp;                                              \
46                                                                         \
47         /*                                                              \
48          * spin lock/unlock provides the needed smp_mb() before/after   \
49          */                                                             \
50         atomic_ops_lock(flags);                                         \
51         temp = v->counter;                                              \
52         temp c_op i;                                                    \
53         v->counter = temp;                                              \
54         atomic_ops_unlock(flags);                                       \
55                                                                         \
56         return temp;                                                    \
57 }
58
59 #define ATOMIC_FETCH_OP(op, c_op, asm_op)                               \
60 static inline int arch_atomic_fetch_##op(int i, atomic_t *v)            \
61 {                                                                       \
62         unsigned long flags;                                            \
63         unsigned int orig;                                              \
64                                                                         \
65         /*                                                              \
66          * spin lock/unlock provides the needed smp_mb() before/after   \
67          */                                                             \
68         atomic_ops_lock(flags);                                         \
69         orig = v->counter;                                              \
70         v->counter c_op i;                                              \
71         atomic_ops_unlock(flags);                                       \
72                                                                         \
73         return orig;                                                    \
74 }
75
76 #define ATOMIC_OPS(op, c_op, asm_op)                                    \
77         ATOMIC_OP(op, c_op, asm_op)                                     \
78         ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
79         ATOMIC_FETCH_OP(op, c_op, asm_op)
80
81 ATOMIC_OPS(add, +=, add)
82 ATOMIC_OPS(sub, -=, sub)
83
84 #undef ATOMIC_OPS
85 #define ATOMIC_OPS(op, c_op, asm_op)                                    \
86         ATOMIC_OP(op, c_op, asm_op)                                     \
87         ATOMIC_FETCH_OP(op, c_op, asm_op)
88
89 ATOMIC_OPS(and, &=, and)
90 ATOMIC_OPS(andnot, &= ~, bic)
91 ATOMIC_OPS(or, |=, or)
92 ATOMIC_OPS(xor, ^=, xor)
93
94 #define arch_atomic_andnot              arch_atomic_andnot
95 #define arch_atomic_fetch_andnot        arch_atomic_fetch_andnot
96
97 #undef ATOMIC_OPS
98 #undef ATOMIC_FETCH_OP
99 #undef ATOMIC_OP_RETURN
100 #undef ATOMIC_OP
101
102 #endif