1#ifndef __ARCH_I386_ATOMIC__
2#define __ARCH_I386_ATOMIC__
3
4#include <linux/compiler.h>
5#include <asm/processor.h>
6
7
8
9
10
11
12
13
14
15
16
17typedef struct { volatile int counter; } atomic_t;
18
19#define ATOMIC_INIT(i) { (i) }
20
21
22
23
24
25
26
27#define atomic_read(v) ((v)->counter)
28
29
30
31
32
33
34
35
36#define atomic_set(v,i) (((v)->counter) = (i))
37
38
39
40
41
42
43
44
45static __inline__ void atomic_add(int i, atomic_t *v)
46{
47 __asm__ __volatile__(
48 LOCK_PREFIX "addl %1,%0"
49 :"+m" (v->counter)
50 :"ir" (i));
51}
52
53
54
55
56
57
58
59
60static __inline__ void atomic_sub(int i, atomic_t *v)
61{
62 __asm__ __volatile__(
63 LOCK_PREFIX "subl %1,%0"
64 :"+m" (v->counter)
65 :"ir" (i));
66}
67
68
69
70
71
72
73
74
75
76
77static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
78{
79 unsigned char c;
80
81 __asm__ __volatile__(
82 LOCK_PREFIX "subl %2,%0; sete %1"
83 :"+m" (v->counter), "=qm" (c)
84 :"ir" (i) : "memory");
85 return c;
86}
87
88
89
90
91
92
93
94static __inline__ void atomic_inc(atomic_t *v)
95{
96 __asm__ __volatile__(
97 LOCK_PREFIX "incl %0"
98 :"+m" (v->counter));
99}
100
101
102
103
104
105
106
107static __inline__ void atomic_dec(atomic_t *v)
108{
109 __asm__ __volatile__(
110 LOCK_PREFIX "decl %0"
111 :"+m" (v->counter));
112}
113
114
115
116
117
118
119
120
121
122static __inline__ int atomic_dec_and_test(atomic_t *v)
123{
124 unsigned char c;
125
126 __asm__ __volatile__(
127 LOCK_PREFIX "decl %0; sete %1"
128 :"+m" (v->counter), "=qm" (c)
129 : : "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__(
146 LOCK_PREFIX "incl %0; sete %1"
147 :"+m" (v->counter), "=qm" (c)
148 : : "memory");
149 return c != 0;
150}
151
152
153
154
155
156
157
158
159
160
161static __inline__ int atomic_add_negative(int i, atomic_t *v)
162{
163 unsigned char c;
164
165 __asm__ __volatile__(
166 LOCK_PREFIX "addl %2,%0; sets %1"
167 :"+m" (v->counter), "=qm" (c)
168 :"ir" (i) : "memory");
169 return c;
170}
171
172
173
174
175
176
177
178
179static __inline__ int atomic_add_return(int i, atomic_t *v)
180{
181 int __i;
182#ifdef CONFIG_M386
183 unsigned long flags;
184 if(unlikely(boot_cpu_data.x86==3))
185 goto no_xadd;
186#endif
187
188 __i = i;
189 __asm__ __volatile__(
190 LOCK_PREFIX "xaddl %0, %1;"
191 :"=r"(i)
192 :"m"(v->counter), "0"(i));
193 return i + __i;
194
195#ifdef CONFIG_M386
196no_xadd:
197 local_irq_save(flags);
198 __i = atomic_read(v);
199 atomic_set(v, i + __i);
200 local_irq_restore(flags);
201 return i + __i;
202#endif
203}
204
205static __inline__ int atomic_sub_return(int i, atomic_t *v)
206{
207 return atomic_add_return(-i,v);
208}
209
210#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
211#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
212
213
214
215
216
217
218
219
220
221
222#define atomic_add_unless(v, a, u) \
223({ \
224 int c, old; \
225 c = atomic_read(v); \
226 for (;;) { \
227 if (unlikely(c == (u))) \
228 break; \
229 old = atomic_cmpxchg((v), c, c + (a)); \
230 if (likely(old == c)) \
231 break; \
232 c = old; \
233 } \
234 c != (u); \
235})
236#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
237
238#define atomic_inc_return(v) (atomic_add_return(1,v))
239#define atomic_dec_return(v) (atomic_sub_return(1,v))
240
241
242#define atomic_clear_mask(mask, addr) \
243__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
244: : "r" (~(mask)),"m" (*addr) : "memory")
245
246#define atomic_set_mask(mask, addr) \
247__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
248: : "r" (mask),"m" (*(addr)) : "memory")
249
250
251#define smp_mb__before_atomic_dec() barrier()
252#define smp_mb__after_atomic_dec() barrier()
253#define smp_mb__before_atomic_inc() barrier()
254#define smp_mb__after_atomic_inc() barrier()
255
256#include <asm-generic/atomic.h>
257#endif
258