Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / include / arch-x86_64 / atomic.h
1 #ifndef _X86_64_ATOMIC_H
2 #define _X86_64_ATOMIC_H
3
4 /* atomic_t should be 32 bit signed type */
5
6 /*
7  * Atomic operations that C can't guarantee us.  Useful for
8  * resource counting etc..
9  */
10
11 /*
12  * Make sure gcc doesn't try to be clever and move things around
13  * on us. We need to use _exactly_ the address the user gave us,
14  * not some alias that contains the same information.
15  */
16 typedef struct { volatile int counter; } atomic_t;
17
18 #define ATOMIC_INIT(i)  { (i) }
19
20 /**
21  * atomic_read - read atomic variable
22  * @v: pointer of type atomic_t
23  * 
24  * Atomically reads the value of @v.
25  */ 
26 #define atomic_read(v)          ((v)->counter)
27
28 /**
29  * atomic_set - set atomic variable
30  * @v: pointer of type atomic_t
31  * @i: required value
32  * 
33  * Atomically sets the value of @v to @i.
34  */ 
35 #define atomic_set(v,i)         (((v)->counter) = (i))
36
37 /**
38  * atomic_add - add integer to atomic variable
39  * @i: integer value to add
40  * @v: pointer of type atomic_t
41  * 
42  * Atomically adds @i to @v.
43  */
44 static __inline__ void atomic_add(int i, atomic_t *v)
45 {
46         __asm__ __volatile__(
47                 "lock ; addl %1,%0"
48                 :"=m" (v->counter)
49                 :"ir" (i), "m" (v->counter));
50 }
51
52 /**
53  * atomic_sub - subtract the atomic variable
54  * @i: integer value to subtract
55  * @v: pointer of type atomic_t
56  * 
57  * Atomically subtracts @i from @v.
58  */
59 static __inline__ void atomic_sub(int i, atomic_t *v)
60 {
61         __asm__ __volatile__(
62                 "lock ; subl %1,%0"
63                 :"=m" (v->counter)
64                 :"ir" (i), "m" (v->counter));
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__(
81                 "lock ; subl %2,%0; sete %1"
82                 :"=m" (v->counter), "=qm" (c)
83                 :"ir" (i), "m" (v->counter) : "memory");
84         return c;
85 }
86
87 /**
88  * atomic_inc - increment atomic variable
89  * @v: pointer of type atomic_t
90  * 
91  * Atomically increments @v by 1.
92  */ 
93 static __inline__ void atomic_inc(atomic_t *v)
94 {
95         __asm__ __volatile__(
96                 "lock ; incl %0"
97                 :"=m" (v->counter)
98                 :"m" (v->counter));
99 }
100
101 /**
102  * atomic_dec - decrement atomic variable
103  * @v: pointer of type atomic_t
104  * 
105  * Atomically decrements @v by 1.
106  */ 
107 static __inline__ void atomic_dec(atomic_t *v)
108 {
109         __asm__ __volatile__(
110                 "lock ; decl %0"
111                 :"=m" (v->counter)
112                 :"m" (v->counter));
113 }
114
115 /**
116  * atomic_dec_and_test - decrement and test
117  * @v: pointer of type atomic_t
118  * 
119  * Atomically decrements @v by 1 and
120  * returns true if the result is 0, or false for all other
121  * cases.
122  */ 
123 static __inline__ int atomic_dec_and_test(atomic_t *v)
124 {
125         unsigned char c;
126
127         __asm__ __volatile__(
128                 "lock ; decl %0; sete %1"
129                 :"=m" (v->counter), "=qm" (c)
130                 :"m" (v->counter) : "memory");
131         return c != 0;
132 }
133
134 /**
135  * atomic_inc_and_test - increment and test 
136  * @v: pointer of type atomic_t
137  * 
138  * Atomically increments @v by 1
139  * and returns true if the result is zero, or false for all
140  * other cases.
141  */ 
142 static __inline__ int atomic_inc_and_test(atomic_t *v)
143 {
144         unsigned char c;
145
146         __asm__ __volatile__(
147                 "lock ; incl %0; sete %1"
148                 :"=m" (v->counter), "=qm" (c)
149                 :"m" (v->counter) : "memory");
150         return c != 0;
151 }
152
153 /**
154  * atomic_add_negative - add and test if negative
155  * @i: integer value to add
156  * @v: pointer of type atomic_t
157  * 
158  * Atomically adds @i to @v and returns true
159  * if the result is negative, or false when
160  * result is greater than or equal to zero.
161  */ 
162 static __inline__ int atomic_add_negative(int i, atomic_t *v)
163 {
164         unsigned char c;
165
166         __asm__ __volatile__(
167                 "lock ; addl %2,%0; sets %1"
168                 :"=m" (v->counter), "=qm" (c)
169                 :"ir" (i), "m" (v->counter) : "memory");
170         return c;
171 }
172
173 /**
174  * atomic_add_return - add and return
175  * @i: integer value to add
176  * @v: pointer of type atomic_t
177  *
178  * Atomically adds @i to @v and returns @i + @v
179  */
180 static __inline__ int atomic_add_return(int i, atomic_t *v)
181 {
182         int __i = i;
183         __asm__ __volatile__(
184                 "lock ; xaddl %0, %1;"
185                 :"=r"(i)
186                 :"m"(v->counter), "0"(i));
187         return i + __i;
188 }
189
190 static __inline__ int atomic_sub_return(int i, atomic_t *v)
191 {
192         return atomic_add_return(-i,v);
193 }
194
195 #define atomic_inc_return(v)  (atomic_add_return(1,v))
196 #define atomic_dec_return(v)  (atomic_sub_return(1,v))
197
198 /* An 64bit atomic type */
199
200 typedef struct { volatile long counter; } atomic64_t;
201
202 #define ATOMIC64_INIT(i)        { (i) }
203
204 /**
205  * atomic64_read - read atomic64 variable
206  * @v: pointer of type atomic64_t
207  *
208  * Atomically reads the value of @v.
209  * Doesn't imply a read memory barrier.
210  */
211 #define atomic64_read(v)                ((v)->counter)
212
213 /**
214  * atomic64_set - set atomic64 variable
215  * @v: pointer to type atomic64_t
216  * @i: required value
217  *
218  * Atomically sets the value of @v to @i.
219  */
220 #define atomic64_set(v,i)               (((v)->counter) = (i))
221
222 /**
223  * atomic64_add - add integer to atomic64 variable
224  * @i: integer value to add
225  * @v: pointer to type atomic64_t
226  *
227  * Atomically adds @i to @v.
228  */
229 static __inline__ void atomic64_add(long i, atomic64_t *v)
230 {
231         __asm__ __volatile__(
232                 "lock ; addq %1,%0"
233                 :"=m" (v->counter)
234                 :"ir" (i), "m" (v->counter));
235 }
236
237 /**
238  * atomic64_sub - subtract the atomic64 variable
239  * @i: integer value to subtract
240  * @v: pointer to type atomic64_t
241  *
242  * Atomically subtracts @i from @v.
243  */
244 static __inline__ void atomic64_sub(long i, atomic64_t *v)
245 {
246         __asm__ __volatile__(
247                 "lock ; subq %1,%0"
248                 :"=m" (v->counter)
249                 :"ir" (i), "m" (v->counter));
250 }
251
252 /**
253  * atomic64_sub_and_test - subtract value from variable and test result
254  * @i: integer value to subtract
255  * @v: pointer to type atomic64_t
256  *
257  * Atomically subtracts @i from @v and returns
258  * true if the result is zero, or false for all
259  * other cases.
260  */
261 static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
262 {
263         unsigned char c;
264
265         __asm__ __volatile__(
266                 "lock ; subq %2,%0; sete %1"
267                 :"=m" (v->counter), "=qm" (c)
268                 :"ir" (i), "m" (v->counter) : "memory");
269         return c;
270 }
271
272 /**
273  * atomic64_inc - increment atomic64 variable
274  * @v: pointer to type atomic64_t
275  *
276  * Atomically increments @v by 1.
277  */
278 static __inline__ void atomic64_inc(atomic64_t *v)
279 {
280         __asm__ __volatile__(
281                 "lock ; incq %0"
282                 :"=m" (v->counter)
283                 :"m" (v->counter));
284 }
285
286 /**
287  * atomic64_dec - decrement atomic64 variable
288  * @v: pointer to type atomic64_t
289  *
290  * Atomically decrements @v by 1.
291  */
292 static __inline__ void atomic64_dec(atomic64_t *v)
293 {
294         __asm__ __volatile__(
295                 "lock ; decq %0"
296                 :"=m" (v->counter)
297                 :"m" (v->counter));
298 }
299
300 /**
301  * atomic64_dec_and_test - decrement and test
302  * @v: pointer to type atomic64_t
303  *
304  * Atomically decrements @v by 1 and
305  * returns true if the result is 0, or false for all other
306  * cases.
307  */
308 static __inline__ int atomic64_dec_and_test(atomic64_t *v)
309 {
310         unsigned char c;
311
312         __asm__ __volatile__(
313                 "lock ; decq %0; sete %1"
314                 :"=m" (v->counter), "=qm" (c)
315                 :"m" (v->counter) : "memory");
316         return c != 0;
317 }
318
319 /**
320  * atomic64_inc_and_test - increment and test
321  * @v: pointer to type atomic64_t
322  *
323  * Atomically increments @v by 1
324  * and returns true if the result is zero, or false for all
325  * other cases.
326  */
327 static __inline__ int atomic64_inc_and_test(atomic64_t *v)
328 {
329         unsigned char c;
330
331         __asm__ __volatile__(
332                 "lock ; incq %0; sete %1"
333                 :"=m" (v->counter), "=qm" (c)
334                 :"m" (v->counter) : "memory");
335         return c != 0;
336 }
337
338 /**
339  * atomic64_add_negative - add and test if negative
340  * @i: integer value to add
341  * @v: pointer to type atomic64_t
342  *
343  * Atomically adds @i to @v and returns true
344  * if the result is negative, or false when
345  * result is greater than or equal to zero.
346  */
347 static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
348 {
349         unsigned char c;
350
351         __asm__ __volatile__(
352                 "lock ; addq %2,%0; sets %1"
353                 :"=m" (v->counter), "=qm" (c)
354                 :"ir" (i), "m" (v->counter) : "memory");
355         return c;
356 }
357
358 /**
359  * atomic64_add_return - add and return
360  * @i: integer value to add
361  * @v: pointer to type atomic64_t
362  *
363  * Atomically adds @i to @v and returns @i + @v
364  */
365 static __inline__ long atomic64_add_return(long i, atomic64_t *v)
366 {
367         long __i = i;
368         __asm__ __volatile__(
369                 "lock ; xaddq %0, %1;"
370                 :"=r"(i)
371                 :"m"(v->counter), "0"(i));
372         return i + __i;
373 }
374
375 static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
376 {
377         return atomic64_add_return(-i,v);
378 }
379
380 #define atomic64_inc_return(v)  (atomic64_add_return(1,v))
381 #define atomic64_dec_return(v)  (atomic64_sub_return(1,v))
382
383 #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
384 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
385
386 /**
387  * atomic_add_unless - add unless the number is a given value
388  * @v: pointer of type atomic_t
389  * @a: the amount to add to v...
390  * @u: ...unless v is equal to u.
391  *
392  * Atomically adds @a to @v, so long as it was not @u.
393  * Returns non-zero if @v was not @u, and zero otherwise.
394  */
395 #define atomic_add_unless(v, a, u)                              \
396 ({                                                              \
397         int c, old;                                             \
398         c = atomic_read(v);                                     \
399         for (;;) {                                              \
400                 if (unlikely(c == (u)))                         \
401                         break;                                  \
402                 old = atomic_cmpxchg((v), c, c + (a));          \
403                 if (likely(old == c))                           \
404                         break;                                  \
405                 c = old;                                        \
406         }                                                       \
407         c != (u);                                               \
408 })
409 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
410
411 /* These are x86-specific, used by some header files */
412 #define atomic_clear_mask(mask, addr) \
413 __asm__ __volatile__("lock ; andl %0,%1" \
414 : : "r" (~(mask)),"m" (*addr) : "memory")
415
416 #define atomic_set_mask(mask, addr) \
417 __asm__ __volatile__("lock ; orl %0,%1" \
418 : : "r" ((unsigned)mask),"m" (*(addr)) : "memory")
419
420 /* Atomic operations are already serializing on x86 */
421 #define smp_mb__before_atomic_dec()     barrier()
422 #define smp_mb__after_atomic_dec()      barrier()
423 #define smp_mb__before_atomic_inc()     barrier()
424 #define smp_mb__after_atomic_inc()      barrier()
425
426 #include <arch-generic/atomic.h>
427 #endif