diff options
Diffstat (limited to 'arch/x86/include/asm/atomic_32.h')
-rw-r--r-- | arch/x86/include/asm/atomic_32.h | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h deleted file mode 100644 index dc5a667ff791..000000000000 --- a/arch/x86/include/asm/atomic_32.h +++ /dev/null | |||
@@ -1,415 +0,0 @@ | |||
1 | #ifndef _ASM_X86_ATOMIC_32_H | ||
2 | #define _ASM_X86_ATOMIC_32_H | ||
3 | |||
4 | #include <linux/compiler.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <asm/processor.h> | ||
7 | #include <asm/cmpxchg.h> | ||
8 | |||
9 | /* | ||
10 | * Atomic operations that C can't guarantee us. Useful for | ||
11 | * resource counting etc.. | ||
12 | */ | ||
13 | |||
14 | #define ATOMIC_INIT(i) { (i) } | ||
15 | |||
16 | /** | ||
17 | * atomic_read - read atomic variable | ||
18 | * @v: pointer of type atomic_t | ||
19 | * | ||
20 | * Atomically reads the value of @v. | ||
21 | */ | ||
22 | static inline int atomic_read(const atomic_t *v) | ||
23 | { | ||
24 | return v->counter; | ||
25 | } | ||
26 | |||
27 | /** | ||
28 | * atomic_set - set atomic variable | ||
29 | * @v: pointer of type atomic_t | ||
30 | * @i: required value | ||
31 | * | ||
32 | * Atomically sets the value of @v to @i. | ||
33 | */ | ||
34 | static inline void atomic_set(atomic_t *v, int i) | ||
35 | { | ||
36 | v->counter = i; | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * atomic_add - add integer to atomic variable | ||
41 | * @i: integer value to add | ||
42 | * @v: pointer of type atomic_t | ||
43 | * | ||
44 | * Atomically adds @i to @v. | ||
45 | */ | ||
46 | static inline void atomic_add(int i, atomic_t *v) | ||
47 | { | ||
48 | asm volatile(LOCK_PREFIX "addl %1,%0" | ||
49 | : "+m" (v->counter) | ||
50 | : "ir" (i)); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * atomic_sub - subtract integer from atomic variable | ||
55 | * @i: integer value to subtract | ||
56 | * @v: pointer of type atomic_t | ||
57 | * | ||
58 | * Atomically subtracts @i from @v. | ||
59 | */ | ||
60 | static inline void atomic_sub(int i, atomic_t *v) | ||
61 | { | ||
62 | asm volatile(LOCK_PREFIX "subl %1,%0" | ||
63 | : "+m" (v->counter) | ||
64 | : "ir" (i)); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * atomic_sub_and_test - subtract value from variable and test result | ||
69 | * @i: integer value to subtract | ||
70 | * @v: pointer of type atomic_t | ||
71 | * | ||
72 | * Atomically subtracts @i from @v and returns | ||
73 | * true if the result is zero, or false for all | ||
74 | * other cases. | ||
75 | */ | ||
76 | static inline int atomic_sub_and_test(int i, atomic_t *v) | ||
77 | { | ||
78 | unsigned char c; | ||
79 | |||
80 | asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" | ||
81 | : "+m" (v->counter), "=qm" (c) | ||
82 | : "ir" (i) : "memory"); | ||
83 | return c; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * atomic_inc - increment atomic variable | ||
88 | * @v: pointer of type atomic_t | ||
89 | * | ||
90 | * Atomically increments @v by 1. | ||
91 | */ | ||
92 | static inline void atomic_inc(atomic_t *v) | ||
93 | { | ||
94 | asm volatile(LOCK_PREFIX "incl %0" | ||
95 | : "+m" (v->counter)); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * atomic_dec - decrement atomic variable | ||
100 | * @v: pointer of type atomic_t | ||
101 | * | ||
102 | * Atomically decrements @v by 1. | ||
103 | */ | ||
104 | static inline void atomic_dec(atomic_t *v) | ||
105 | { | ||
106 | asm volatile(LOCK_PREFIX "decl %0" | ||
107 | : "+m" (v->counter)); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * atomic_dec_and_test - decrement and test | ||
112 | * @v: pointer of type atomic_t | ||
113 | * | ||
114 | * Atomically decrements @v by 1 and | ||
115 | * returns true if the result is 0, or false for all other | ||
116 | * cases. | ||
117 | */ | ||
118 | static inline int atomic_dec_and_test(atomic_t *v) | ||
119 | { | ||
120 | unsigned char c; | ||
121 | |||
122 | asm volatile(LOCK_PREFIX "decl %0; sete %1" | ||
123 | : "+m" (v->counter), "=qm" (c) | ||
124 | : : "memory"); | ||
125 | return c != 0; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * atomic_inc_and_test - increment and test | ||
130 | * @v: pointer of type atomic_t | ||
131 | * | ||
132 | * Atomically increments @v by 1 | ||
133 | * and returns true if the result is zero, or false for all | ||
134 | * other cases. | ||
135 | */ | ||
136 | static inline int atomic_inc_and_test(atomic_t *v) | ||
137 | { | ||
138 | unsigned char c; | ||
139 | |||
140 | asm volatile(LOCK_PREFIX "incl %0; sete %1" | ||
141 | : "+m" (v->counter), "=qm" (c) | ||
142 | : : "memory"); | ||
143 | return c != 0; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * atomic_add_negative - add and test if negative | ||
148 | * @v: pointer of type atomic_t | ||
149 | * @i: integer value to add | ||
150 | * | ||
151 | * Atomically adds @i to @v and returns true | ||
152 | * if the result is negative, or false when | ||
153 | * result is greater than or equal to zero. | ||
154 | */ | ||
155 | static inline int atomic_add_negative(int i, atomic_t *v) | ||
156 | { | ||
157 | unsigned char c; | ||
158 | |||
159 | asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" | ||
160 | : "+m" (v->counter), "=qm" (c) | ||
161 | : "ir" (i) : "memory"); | ||
162 | return c; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * atomic_add_return - add integer and return | ||
167 | * @v: pointer of type atomic_t | ||
168 | * @i: integer value to add | ||
169 | * | ||
170 | * Atomically adds @i to @v and returns @i + @v | ||
171 | */ | ||
172 | static inline int atomic_add_return(int i, atomic_t *v) | ||
173 | { | ||
174 | int __i; | ||
175 | #ifdef CONFIG_M386 | ||
176 | unsigned long flags; | ||
177 | if (unlikely(boot_cpu_data.x86 <= 3)) | ||
178 | goto no_xadd; | ||
179 | #endif | ||
180 | /* Modern 486+ processor */ | ||
181 | __i = i; | ||
182 | asm volatile(LOCK_PREFIX "xaddl %0, %1" | ||
183 | : "+r" (i), "+m" (v->counter) | ||
184 | : : "memory"); | ||
185 | return i + __i; | ||
186 | |||
187 | #ifdef CONFIG_M386 | ||
188 | no_xadd: /* Legacy 386 processor */ | ||
189 | local_irq_save(flags); | ||
190 | __i = atomic_read(v); | ||
191 | atomic_set(v, i + __i); | ||
192 | local_irq_restore(flags); | ||
193 | return i + __i; | ||
194 | #endif | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * atomic_sub_return - subtract integer and return | ||
199 | * @v: pointer of type atomic_t | ||
200 | * @i: integer value to subtract | ||
201 | * | ||
202 | * Atomically subtracts @i from @v and returns @v - @i | ||
203 | */ | ||
204 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
205 | { | ||
206 | return atomic_add_return(-i, v); | ||
207 | } | ||
208 | |||
209 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
210 | { | ||
211 | return cmpxchg(&v->counter, old, new); | ||
212 | } | ||
213 | |||
214 | static inline int atomic_xchg(atomic_t *v, int new) | ||
215 | { | ||
216 | return xchg(&v->counter, new); | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * atomic_add_unless - add unless the number is already a given value | ||
221 | * @v: pointer of type atomic_t | ||
222 | * @a: the amount to add to v... | ||
223 | * @u: ...unless v is equal to u. | ||
224 | * | ||
225 | * Atomically adds @a to @v, so long as @v was not already @u. | ||
226 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
227 | */ | ||
228 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
229 | { | ||
230 | int c, old; | ||
231 | c = atomic_read(v); | ||
232 | for (;;) { | ||
233 | if (unlikely(c == (u))) | ||
234 | break; | ||
235 | old = atomic_cmpxchg((v), c, c + (a)); | ||
236 | if (likely(old == c)) | ||
237 | break; | ||
238 | c = old; | ||
239 | } | ||
240 | return c != (u); | ||
241 | } | ||
242 | |||
243 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
244 | |||
245 | #define atomic_inc_return(v) (atomic_add_return(1, v)) | ||
246 | #define atomic_dec_return(v) (atomic_sub_return(1, v)) | ||
247 | |||
248 | /* These are x86-specific, used by some header files */ | ||
249 | #define atomic_clear_mask(mask, addr) \ | ||
250 | asm volatile(LOCK_PREFIX "andl %0,%1" \ | ||
251 | : : "r" (~(mask)), "m" (*(addr)) : "memory") | ||
252 | |||
253 | #define atomic_set_mask(mask, addr) \ | ||
254 | asm volatile(LOCK_PREFIX "orl %0,%1" \ | ||
255 | : : "r" (mask), "m" (*(addr)) : "memory") | ||
256 | |||
257 | /* Atomic operations are already serializing on x86 */ | ||
258 | #define smp_mb__before_atomic_dec() barrier() | ||
259 | #define smp_mb__after_atomic_dec() barrier() | ||
260 | #define smp_mb__before_atomic_inc() barrier() | ||
261 | #define smp_mb__after_atomic_inc() barrier() | ||
262 | |||
263 | /* An 64bit atomic type */ | ||
264 | |||
265 | typedef struct { | ||
266 | u64 __aligned(8) counter; | ||
267 | } atomic64_t; | ||
268 | |||
269 | #define ATOMIC64_INIT(val) { (val) } | ||
270 | |||
271 | extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); | ||
272 | |||
273 | /** | ||
274 | * atomic64_xchg - xchg atomic64 variable | ||
275 | * @ptr: pointer to type atomic64_t | ||
276 | * @new_val: value to assign | ||
277 | * | ||
278 | * Atomically xchgs the value of @ptr to @new_val and returns | ||
279 | * the old value. | ||
280 | */ | ||
281 | extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); | ||
282 | |||
283 | /** | ||
284 | * atomic64_set - set atomic64 variable | ||
285 | * @ptr: pointer to type atomic64_t | ||
286 | * @new_val: value to assign | ||
287 | * | ||
288 | * Atomically sets the value of @ptr to @new_val. | ||
289 | */ | ||
290 | extern void atomic64_set(atomic64_t *ptr, u64 new_val); | ||
291 | |||
292 | /** | ||
293 | * atomic64_read - read atomic64 variable | ||
294 | * @ptr: pointer to type atomic64_t | ||
295 | * | ||
296 | * Atomically reads the value of @ptr and returns it. | ||
297 | */ | ||
298 | static inline u64 atomic64_read(atomic64_t *ptr) | ||
299 | { | ||
300 | u64 res; | ||
301 | |||
302 | /* | ||
303 | * Note, we inline this atomic64_t primitive because | ||
304 | * it only clobbers EAX/EDX and leaves the others | ||
305 | * untouched. We also (somewhat subtly) rely on the | ||
306 | * fact that cmpxchg8b returns the current 64-bit value | ||
307 | * of the memory location we are touching: | ||
308 | */ | ||
309 | asm volatile( | ||
310 | "mov %%ebx, %%eax\n\t" | ||
311 | "mov %%ecx, %%edx\n\t" | ||
312 | LOCK_PREFIX "cmpxchg8b %1\n" | ||
313 | : "=&A" (res) | ||
314 | : "m" (*ptr) | ||
315 | ); | ||
316 | |||
317 | return res; | ||
318 | } | ||
319 | |||
320 | extern u64 atomic64_read(atomic64_t *ptr); | ||
321 | |||
322 | /** | ||
323 | * atomic64_add_return - add and return | ||
324 | * @delta: integer value to add | ||
325 | * @ptr: pointer to type atomic64_t | ||
326 | * | ||
327 | * Atomically adds @delta to @ptr and returns @delta + *@ptr | ||
328 | */ | ||
329 | extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); | ||
330 | |||
331 | /* | ||
332 | * Other variants with different arithmetic operators: | ||
333 | */ | ||
334 | extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); | ||
335 | extern u64 atomic64_inc_return(atomic64_t *ptr); | ||
336 | extern u64 atomic64_dec_return(atomic64_t *ptr); | ||
337 | |||
338 | /** | ||
339 | * atomic64_add - add integer to atomic64 variable | ||
340 | * @delta: integer value to add | ||
341 | * @ptr: pointer to type atomic64_t | ||
342 | * | ||
343 | * Atomically adds @delta to @ptr. | ||
344 | */ | ||
345 | extern void atomic64_add(u64 delta, atomic64_t *ptr); | ||
346 | |||
347 | /** | ||
348 | * atomic64_sub - subtract the atomic64 variable | ||
349 | * @delta: integer value to subtract | ||
350 | * @ptr: pointer to type atomic64_t | ||
351 | * | ||
352 | * Atomically subtracts @delta from @ptr. | ||
353 | */ | ||
354 | extern void atomic64_sub(u64 delta, atomic64_t *ptr); | ||
355 | |||
356 | /** | ||
357 | * atomic64_sub_and_test - subtract value from variable and test result | ||
358 | * @delta: integer value to subtract | ||
359 | * @ptr: pointer to type atomic64_t | ||
360 | * | ||
361 | * Atomically subtracts @delta from @ptr and returns | ||
362 | * true if the result is zero, or false for all | ||
363 | * other cases. | ||
364 | */ | ||
365 | extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); | ||
366 | |||
367 | /** | ||
368 | * atomic64_inc - increment atomic64 variable | ||
369 | * @ptr: pointer to type atomic64_t | ||
370 | * | ||
371 | * Atomically increments @ptr by 1. | ||
372 | */ | ||
373 | extern void atomic64_inc(atomic64_t *ptr); | ||
374 | |||
375 | /** | ||
376 | * atomic64_dec - decrement atomic64 variable | ||
377 | * @ptr: pointer to type atomic64_t | ||
378 | * | ||
379 | * Atomically decrements @ptr by 1. | ||
380 | */ | ||
381 | extern void atomic64_dec(atomic64_t *ptr); | ||
382 | |||
383 | /** | ||
384 | * atomic64_dec_and_test - decrement and test | ||
385 | * @ptr: pointer to type atomic64_t | ||
386 | * | ||
387 | * Atomically decrements @ptr by 1 and | ||
388 | * returns true if the result is 0, or false for all other | ||
389 | * cases. | ||
390 | */ | ||
391 | extern int atomic64_dec_and_test(atomic64_t *ptr); | ||
392 | |||
393 | /** | ||
394 | * atomic64_inc_and_test - increment and test | ||
395 | * @ptr: pointer to type atomic64_t | ||
396 | * | ||
397 | * Atomically increments @ptr by 1 | ||
398 | * and returns true if the result is zero, or false for all | ||
399 | * other cases. | ||
400 | */ | ||
401 | extern int atomic64_inc_and_test(atomic64_t *ptr); | ||
402 | |||
403 | /** | ||
404 | * atomic64_add_negative - add and test if negative | ||
405 | * @delta: integer value to add | ||
406 | * @ptr: pointer to type atomic64_t | ||
407 | * | ||
408 | * Atomically adds @delta to @ptr and returns true | ||
409 | * if the result is negative, or false when | ||
410 | * result is greater than or equal to zero. | ||
411 | */ | ||
412 | extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); | ||
413 | |||
414 | #include <asm-generic/atomic-long.h> | ||
415 | #endif /* _ASM_X86_ATOMIC_32_H */ | ||