Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/parisc/include/asm/atomic.h
26298 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/* Copyright (C) 2000 Philipp Rumpf <[email protected]>
3
* Copyright (C) 2006 Kyle McMartin <[email protected]>
4
*/
5
6
#ifndef _ASM_PARISC_ATOMIC_H_
7
#define _ASM_PARISC_ATOMIC_H_
8
9
#include <linux/types.h>
10
#include <asm/cmpxchg.h>
11
#include <asm/barrier.h>
12
13
/*
14
* Atomic operations that C can't guarantee us. Useful for
15
* resource counting etc..
16
*
17
* And probably incredibly slow on parisc. OTOH, we don't
18
* have to write any serious assembly. prumpf
19
*/
20
21
#ifdef CONFIG_SMP
22
#include <asm/spinlock.h>
23
#include <asm/cache.h> /* we use L1_CACHE_BYTES */
24
25
/* Use an array of spinlocks for our atomic_ts.
26
* Hash function to index into a different SPINLOCK.
27
* Since "a" is usually an address, use one spinlock per cacheline.
28
*/
29
# define ATOMIC_HASH_SIZE 4
30
# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) (a))/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
31
32
extern arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
33
34
/* Can't use raw_spin_lock_irq because of #include problems, so
35
* this is the substitute */
36
#define _atomic_spin_lock_irqsave(l,f) do { \
37
arch_spinlock_t *s = ATOMIC_HASH(l); \
38
local_irq_save(f); \
39
arch_spin_lock(s); \
40
} while(0)
41
42
#define _atomic_spin_unlock_irqrestore(l,f) do { \
43
arch_spinlock_t *s = ATOMIC_HASH(l); \
44
arch_spin_unlock(s); \
45
local_irq_restore(f); \
46
} while(0)
47
48
49
#else
50
# define _atomic_spin_lock_irqsave(l,f) do { local_irq_save(f); } while (0)
51
# define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
52
#endif
53
54
/*
55
* Note that we need not lock read accesses - aligned word writes/reads
56
* are atomic, so a reader never sees inconsistent values.
57
*/
58
59
static __inline__ void arch_atomic_set(atomic_t *v, int i)
60
{
61
unsigned long flags;
62
_atomic_spin_lock_irqsave(v, flags);
63
64
v->counter = i;
65
66
_atomic_spin_unlock_irqrestore(v, flags);
67
}
68
69
#define arch_atomic_set_release(v, i) arch_atomic_set((v), (i))
70
71
static __inline__ int arch_atomic_read(const atomic_t *v)
72
{
73
return READ_ONCE((v)->counter);
74
}
75
76
#define ATOMIC_OP(op, c_op) \
77
static __inline__ void arch_atomic_##op(int i, atomic_t *v) \
78
{ \
79
unsigned long flags; \
80
\
81
_atomic_spin_lock_irqsave(v, flags); \
82
v->counter c_op i; \
83
_atomic_spin_unlock_irqrestore(v, flags); \
84
}
85
86
#define ATOMIC_OP_RETURN(op, c_op) \
87
static __inline__ int arch_atomic_##op##_return(int i, atomic_t *v) \
88
{ \
89
unsigned long flags; \
90
int ret; \
91
\
92
_atomic_spin_lock_irqsave(v, flags); \
93
ret = (v->counter c_op i); \
94
_atomic_spin_unlock_irqrestore(v, flags); \
95
\
96
return ret; \
97
}
98
99
#define ATOMIC_FETCH_OP(op, c_op) \
100
static __inline__ int arch_atomic_fetch_##op(int i, atomic_t *v) \
101
{ \
102
unsigned long flags; \
103
int ret; \
104
\
105
_atomic_spin_lock_irqsave(v, flags); \
106
ret = v->counter; \
107
v->counter c_op i; \
108
_atomic_spin_unlock_irqrestore(v, flags); \
109
\
110
return ret; \
111
}
112
113
#define ATOMIC_OPS(op, c_op) \
114
ATOMIC_OP(op, c_op) \
115
ATOMIC_OP_RETURN(op, c_op) \
116
ATOMIC_FETCH_OP(op, c_op)
117
118
ATOMIC_OPS(add, +=)
119
ATOMIC_OPS(sub, -=)
120
121
#define arch_atomic_add_return arch_atomic_add_return
122
#define arch_atomic_sub_return arch_atomic_sub_return
123
#define arch_atomic_fetch_add arch_atomic_fetch_add
124
#define arch_atomic_fetch_sub arch_atomic_fetch_sub
125
126
#undef ATOMIC_OPS
127
#define ATOMIC_OPS(op, c_op) \
128
ATOMIC_OP(op, c_op) \
129
ATOMIC_FETCH_OP(op, c_op)
130
131
ATOMIC_OPS(and, &=)
132
ATOMIC_OPS(or, |=)
133
ATOMIC_OPS(xor, ^=)
134
135
#define arch_atomic_fetch_and arch_atomic_fetch_and
136
#define arch_atomic_fetch_or arch_atomic_fetch_or
137
#define arch_atomic_fetch_xor arch_atomic_fetch_xor
138
139
#undef ATOMIC_OPS
140
#undef ATOMIC_FETCH_OP
141
#undef ATOMIC_OP_RETURN
142
#undef ATOMIC_OP
143
144
#ifdef CONFIG_64BIT
145
146
#define ATOMIC64_INIT(i) { (i) }
147
148
#define ATOMIC64_OP(op, c_op) \
149
static __inline__ void arch_atomic64_##op(s64 i, atomic64_t *v) \
150
{ \
151
unsigned long flags; \
152
\
153
_atomic_spin_lock_irqsave(v, flags); \
154
v->counter c_op i; \
155
_atomic_spin_unlock_irqrestore(v, flags); \
156
}
157
158
#define ATOMIC64_OP_RETURN(op, c_op) \
159
static __inline__ s64 arch_atomic64_##op##_return(s64 i, atomic64_t *v) \
160
{ \
161
unsigned long flags; \
162
s64 ret; \
163
\
164
_atomic_spin_lock_irqsave(v, flags); \
165
ret = (v->counter c_op i); \
166
_atomic_spin_unlock_irqrestore(v, flags); \
167
\
168
return ret; \
169
}
170
171
#define ATOMIC64_FETCH_OP(op, c_op) \
172
static __inline__ s64 arch_atomic64_fetch_##op(s64 i, atomic64_t *v) \
173
{ \
174
unsigned long flags; \
175
s64 ret; \
176
\
177
_atomic_spin_lock_irqsave(v, flags); \
178
ret = v->counter; \
179
v->counter c_op i; \
180
_atomic_spin_unlock_irqrestore(v, flags); \
181
\
182
return ret; \
183
}
184
185
#define ATOMIC64_OPS(op, c_op) \
186
ATOMIC64_OP(op, c_op) \
187
ATOMIC64_OP_RETURN(op, c_op) \
188
ATOMIC64_FETCH_OP(op, c_op)
189
190
ATOMIC64_OPS(add, +=)
191
ATOMIC64_OPS(sub, -=)
192
193
#define arch_atomic64_add_return arch_atomic64_add_return
194
#define arch_atomic64_sub_return arch_atomic64_sub_return
195
#define arch_atomic64_fetch_add arch_atomic64_fetch_add
196
#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub
197
198
#undef ATOMIC64_OPS
199
#define ATOMIC64_OPS(op, c_op) \
200
ATOMIC64_OP(op, c_op) \
201
ATOMIC64_FETCH_OP(op, c_op)
202
203
ATOMIC64_OPS(and, &=)
204
ATOMIC64_OPS(or, |=)
205
ATOMIC64_OPS(xor, ^=)
206
207
#define arch_atomic64_fetch_and arch_atomic64_fetch_and
208
#define arch_atomic64_fetch_or arch_atomic64_fetch_or
209
#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor
210
211
#undef ATOMIC64_OPS
212
#undef ATOMIC64_FETCH_OP
213
#undef ATOMIC64_OP_RETURN
214
#undef ATOMIC64_OP
215
216
static __inline__ void
217
arch_atomic64_set(atomic64_t *v, s64 i)
218
{
219
unsigned long flags;
220
_atomic_spin_lock_irqsave(v, flags);
221
222
v->counter = i;
223
224
_atomic_spin_unlock_irqrestore(v, flags);
225
}
226
227
#define arch_atomic64_set_release(v, i) arch_atomic64_set((v), (i))
228
229
static __inline__ s64
230
arch_atomic64_read(const atomic64_t *v)
231
{
232
return READ_ONCE((v)->counter);
233
}
234
235
#endif /* !CONFIG_64BIT */
236
237
238
#endif /* _ASM_PARISC_ATOMIC_H_ */
239
240