1#ifndef _ASM_X86_ATOMIC_64_H
2#define _ASM_X86_ATOMIC_64_H
3
4#include <asm/alternative.h>
5#include <asm/cmpxchg.h>
6
7
8
9
10
11
12
13
14
15
16
17
18
19typedef struct {
20 int counter;
21} atomic_t;
22
23#define ATOMIC_INIT(i) { (i) }
24
25
26
27
28
29
30
31#define atomic_read(v) ((v)->counter)
32
33
34
35
36
37
38
39
40#define atomic_set(v, i) (((v)->counter) = (i))
41
42
43
44
45
46
47
48
49static inline void atomic_add(int i, atomic_t *v)
50{
51 asm volatile(LOCK_PREFIX "addl %1,%0"
52 : "=m" (v->counter)
53 : "ir" (i), "m" (v->counter));
54}
55
56
57
58
59
60
61
62
63static inline void atomic_sub(int i, atomic_t *v)
64{
65 asm volatile(LOCK_PREFIX "subl %1,%0"
66 : "=m" (v->counter)
67 : "ir" (i), "m" (v->counter));
68}
69
70
71
72
73
74
75
76
77
78
79static inline int atomic_sub_and_test(int i, atomic_t *v)
80{
81 unsigned char c;
82
83 asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
84 : "=m" (v->counter), "=qm" (c)
85 : "ir" (i), "m" (v->counter) : "memory");
86 return c;
87}
88
89
90
91
92
93
94
95static inline void atomic_inc(atomic_t *v)
96{
97 asm volatile(LOCK_PREFIX "incl %0"
98 : "=m" (v->counter)
99 : "m" (v->counter));
100}
101
102
103
104
105
106
107
108static inline void atomic_dec(atomic_t *v)
109{
110 asm volatile(LOCK_PREFIX "decl %0"
111 : "=m" (v->counter)
112 : "m" (v->counter));
113}
114
115
116
117
118
119
120
121
122
123static inline int atomic_dec_and_test(atomic_t *v)
124{
125 unsigned char c;
126
127 asm volatile(LOCK_PREFIX "decl %0; sete %1"
128 : "=m" (v->counter), "=qm" (c)
129 : "m" (v->counter) : "memory");
130 return c != 0;
131}
132
133
134
135
136
137
138
139
140
141static inline int atomic_inc_and_test(atomic_t *v)
142{
143 unsigned char c;
144
145 asm volatile(LOCK_PREFIX "incl %0; sete %1"
146 : "=m" (v->counter), "=qm" (c)
147 : "m" (v->counter) : "memory");
148 return c != 0;
149}
150
151
152
153
154
155
156
157
158
159
160static inline int atomic_add_negative(int i, atomic_t *v)
161{
162 unsigned char c;
163
164 asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
165 : "=m" (v->counter), "=qm" (c)
166 : "ir" (i), "m" (v->counter) : "memory");
167 return c;
168}
169
170
171
172
173
174
175
176
177static inline int atomic_add_return(int i, atomic_t *v)
178{
179 int __i = i;
180 asm volatile(LOCK_PREFIX "xaddl %0, %1"
181 : "+r" (i), "+m" (v->counter)
182 : : "memory");
183 return i + __i;
184}
185
186static inline int atomic_sub_return(int i, atomic_t *v)
187{
188 return atomic_add_return(-i, v);
189}
190
191#define atomic_inc_return(v) (atomic_add_return(1, v))
192#define atomic_dec_return(v) (atomic_sub_return(1, v))
193
194
195
196typedef struct {
197 long counter;
198} atomic64_t;
199
200#define ATOMIC64_INIT(i) { (i) }
201
202
203
204
205
206
207
208
209#define atomic64_read(v) ((v)->counter)
210
211
212
213
214
215
216
217
218#define atomic64_set(v, i) (((v)->counter) = (i))
219
220
221
222
223
224
225
226
227static inline void atomic64_add(long i, atomic64_t *v)
228{
229 asm volatile(LOCK_PREFIX "addq %1,%0"
230 : "=m" (v->counter)
231 : "er" (i), "m" (v->counter));
232}
233
234
235
236
237
238
239
240
241static inline void atomic64_sub(long i, atomic64_t *v)
242{
243 asm volatile(LOCK_PREFIX "subq %1,%0"
244 : "=m" (v->counter)
245 : "er" (i), "m" (v->counter));
246}
247
248
249
250
251
252
253
254
255
256
257static inline int atomic64_sub_and_test(long i, atomic64_t *v)
258{
259 unsigned char c;
260
261 asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
262 : "=m" (v->counter), "=qm" (c)
263 : "er" (i), "m" (v->counter) : "memory");
264 return c;
265}
266
267
268
269
270
271
272
273static inline void atomic64_inc(atomic64_t *v)
274{
275 asm volatile(LOCK_PREFIX "incq %0"
276 : "=m" (v->counter)
277 : "m" (v->counter));
278}
279
280
281
282
283
284
285
286static inline void atomic64_dec(atomic64_t *v)
287{
288 asm volatile(LOCK_PREFIX "decq %0"
289 : "=m" (v->counter)
290 : "m" (v->counter));
291}
292
293
294
295
296
297
298
299
300
301static inline int atomic64_dec_and_test(atomic64_t *v)
302{
303 unsigned char c;
304
305 asm volatile(LOCK_PREFIX "decq %0; sete %1"
306 : "=m" (v->counter), "=qm" (c)
307 : "m" (v->counter) : "memory");
308 return c != 0;
309}
310
311
312
313
314
315
316
317
318
319static inline int atomic64_inc_and_test(atomic64_t *v)
320{
321 unsigned char c;
322
323 asm volatile(LOCK_PREFIX "incq %0; sete %1"
324 : "=m" (v->counter), "=qm" (c)
325 : "m" (v->counter) : "memory");
326 return c != 0;
327}
328
329
330
331
332
333
334
335
336
337
338static inline int atomic64_add_negative(long i, atomic64_t *v)
339{
340 unsigned char c;
341
342 asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
343 : "=m" (v->counter), "=qm" (c)
344 : "er" (i), "m" (v->counter) : "memory");
345 return c;
346}
347
348
349
350
351
352
353
354
355static inline long atomic64_add_return(long i, atomic64_t *v)
356{
357 long __i = i;
358 asm volatile(LOCK_PREFIX "xaddq %0, %1;"
359 : "+r" (i), "+m" (v->counter)
360 : : "memory");
361 return i + __i;
362}
363
364static inline long atomic64_sub_return(long i, atomic64_t *v)
365{
366 return atomic64_add_return(-i, v);
367}
368
369#define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
370#define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
371
372#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
373#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
374
375#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
376#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
377
378
379
380
381
382
383
384
385
386
387static inline int atomic_add_unless(atomic_t *v, int a, int u)
388{
389 int c, old;
390 c = atomic_read(v);
391 for (;;) {
392 if (unlikely(c == (u)))
393 break;
394 old = atomic_cmpxchg((v), c, c + (a));
395 if (likely(old == c))
396 break;
397 c = old;
398 }
399 return c != (u);
400}
401
402#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
403
404
405
406
407
408
409
410
411
412
413static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
414{
415 long c, old;
416 c = atomic64_read(v);
417 for (;;) {
418 if (unlikely(c == (u)))
419 break;
420 old = atomic64_cmpxchg((v), c, c + (a));
421 if (likely(old == c))
422 break;
423 c = old;
424 }
425 return c != (u);
426}
427
428
429
430
431
432
433
434
435static inline short int atomic_inc_short(short int *v)
436{
437 asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v));
438 return *v;
439}
440
441
442
443
444
445
446
447
448
449static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
450{
451 asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2));
452}
453
454#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
455
456
457#define atomic_clear_mask(mask, addr) \
458 asm volatile(LOCK_PREFIX "andl %0,%1" \
459 : : "r" (~(mask)), "m" (*(addr)) : "memory")
460
461#define atomic_set_mask(mask, addr) \
462 asm volatile(LOCK_PREFIX "orl %0,%1" \
463 : : "r" ((unsigned)(mask)), "m" (*(addr)) \
464 : "memory")
465
466
467#define smp_mb__before_atomic_dec() barrier()
468#define smp_mb__after_atomic_dec() barrier()
469#define smp_mb__before_atomic_inc() barrier()
470#define smp_mb__after_atomic_inc() barrier()
471
472#include <asm-generic/atomic.h>
473#endif
474