Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arc/include/asm/atomic-spinlock.h
26481 views
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
#define arch_atomic_fetch_add arch_atomic_fetch_add
85
#define arch_atomic_fetch_sub arch_atomic_fetch_sub
86
#define arch_atomic_add_return arch_atomic_add_return
87
#define arch_atomic_sub_return arch_atomic_sub_return
88
89
#undef ATOMIC_OPS
90
#define ATOMIC_OPS(op, c_op, asm_op) \
91
ATOMIC_OP(op, c_op, asm_op) \
92
ATOMIC_FETCH_OP(op, c_op, asm_op)
93
94
ATOMIC_OPS(and, &=, and)
95
ATOMIC_OPS(andnot, &= ~, bic)
96
ATOMIC_OPS(or, |=, or)
97
ATOMIC_OPS(xor, ^=, xor)
98
99
#define arch_atomic_andnot arch_atomic_andnot
100
101
#define arch_atomic_fetch_and arch_atomic_fetch_and
102
#define arch_atomic_fetch_andnot arch_atomic_fetch_andnot
103
#define arch_atomic_fetch_or arch_atomic_fetch_or
104
#define arch_atomic_fetch_xor arch_atomic_fetch_xor
105
106
#undef ATOMIC_OPS
107
#undef ATOMIC_FETCH_OP
108
#undef ATOMIC_OP_RETURN
109
#undef ATOMIC_OP
110
111
#endif
112
113