Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / include / asm-alpha / atomic.h
1 #ifndef _ALPHA_ATOMIC_H
2 #define _ALPHA_ATOMIC_H
3
4 #include <asm/barrier.h>
5 #include <asm/system.h>
6
7 /*
8  * Atomic operations that C can't guarantee us.  Useful for
9  * resource counting etc...
10  *
11  * But use these as seldom as possible since they are much slower
12  * than regular operations.
13  */
14
15
16 /*
17  * Counter is volatile to make sure gcc doesn't try to be clever
18  * and move things around on us. We need to use _exactly_ the address
19  * the user gave us, not some alias that contains the same information.
20  */
21 typedef struct { volatile int counter; } atomic_t;
22 typedef struct { volatile long counter; } atomic64_t;
23
24 #define ATOMIC_INIT(i)          ( (atomic_t) { (i) } )
25 #define ATOMIC64_INIT(i)        ( (atomic64_t) { (i) } )
26
27 #define atomic_read(v)          ((v)->counter + 0)
28 #define atomic64_read(v)        ((v)->counter + 0)
29
30 #define atomic_set(v,i)         ((v)->counter = (i))
31 #define atomic64_set(v,i)       ((v)->counter = (i))
32
33 /*
34  * To get proper branch prediction for the main line, we must branch
35  * forward to code at the end of this object's .text section, then
36  * branch back to restart the operation.
37  */
38
39 static __inline__ void atomic_add(int i, atomic_t * v)
40 {
41         unsigned long temp;
42         __asm__ __volatile__(
43         "1:     ldl_l %0,%1\n"
44         "       addl %0,%2,%0\n"
45         "       stl_c %0,%1\n"
46         "       beq %0,2f\n"
47         ".subsection 2\n"
48         "2:     br 1b\n"
49         ".previous"
50         :"=&r" (temp), "=m" (v->counter)
51         :"Ir" (i), "m" (v->counter));
52 }
53
54 static __inline__ void atomic64_add(long i, atomic64_t * v)
55 {
56         unsigned long temp;
57         __asm__ __volatile__(
58         "1:     ldq_l %0,%1\n"
59         "       addq %0,%2,%0\n"
60         "       stq_c %0,%1\n"
61         "       beq %0,2f\n"
62         ".subsection 2\n"
63         "2:     br 1b\n"
64         ".previous"
65         :"=&r" (temp), "=m" (v->counter)
66         :"Ir" (i), "m" (v->counter));
67 }
68
69 static __inline__ void atomic_sub(int i, atomic_t * v)
70 {
71         unsigned long temp;
72         __asm__ __volatile__(
73         "1:     ldl_l %0,%1\n"
74         "       subl %0,%2,%0\n"
75         "       stl_c %0,%1\n"
76         "       beq %0,2f\n"
77         ".subsection 2\n"
78         "2:     br 1b\n"
79         ".previous"
80         :"=&r" (temp), "=m" (v->counter)
81         :"Ir" (i), "m" (v->counter));
82 }
83
84 static __inline__ void atomic64_sub(long i, atomic64_t * v)
85 {
86         unsigned long temp;
87         __asm__ __volatile__(
88         "1:     ldq_l %0,%1\n"
89         "       subq %0,%2,%0\n"
90         "       stq_c %0,%1\n"
91         "       beq %0,2f\n"
92         ".subsection 2\n"
93         "2:     br 1b\n"
94         ".previous"
95         :"=&r" (temp), "=m" (v->counter)
96         :"Ir" (i), "m" (v->counter));
97 }
98
99
100 /*
101  * Same as above, but return the result value
102  */
103 static inline int atomic_add_return(int i, atomic_t *v)
104 {
105         long temp, result;
106         smp_mb();
107         __asm__ __volatile__(
108         "1:     ldl_l %0,%1\n"
109         "       addl %0,%3,%2\n"
110         "       addl %0,%3,%0\n"
111         "       stl_c %0,%1\n"
112         "       beq %0,2f\n"
113         ".subsection 2\n"
114         "2:     br 1b\n"
115         ".previous"
116         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
117         :"Ir" (i), "m" (v->counter) : "memory");
118         smp_mb();
119         return result;
120 }
121
122 static __inline__ long atomic64_add_return(long i, atomic64_t * v)
123 {
124         long temp, result;
125         smp_mb();
126         __asm__ __volatile__(
127         "1:     ldq_l %0,%1\n"
128         "       addq %0,%3,%2\n"
129         "       addq %0,%3,%0\n"
130         "       stq_c %0,%1\n"
131         "       beq %0,2f\n"
132         ".subsection 2\n"
133         "2:     br 1b\n"
134         ".previous"
135         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
136         :"Ir" (i), "m" (v->counter) : "memory");
137         smp_mb();
138         return result;
139 }
140
141 static __inline__ long atomic_sub_return(int i, atomic_t * v)
142 {
143         long temp, result;
144         smp_mb();
145         __asm__ __volatile__(
146         "1:     ldl_l %0,%1\n"
147         "       subl %0,%3,%2\n"
148         "       subl %0,%3,%0\n"
149         "       stl_c %0,%1\n"
150         "       beq %0,2f\n"
151         ".subsection 2\n"
152         "2:     br 1b\n"
153         ".previous"
154         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
155         :"Ir" (i), "m" (v->counter) : "memory");
156         smp_mb();
157         return result;
158 }
159
160 static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
161 {
162         long temp, result;
163         smp_mb();
164         __asm__ __volatile__(
165         "1:     ldq_l %0,%1\n"
166         "       subq %0,%3,%2\n"
167         "       subq %0,%3,%0\n"
168         "       stq_c %0,%1\n"
169         "       beq %0,2f\n"
170         ".subsection 2\n"
171         "2:     br 1b\n"
172         ".previous"
173         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
174         :"Ir" (i), "m" (v->counter) : "memory");
175         smp_mb();
176         return result;
177 }
178
179 #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
180 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
181
182 #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
183 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
184
185 /**
186  * atomic_add_unless - add unless the number is a given value
187  * @v: pointer of type atomic_t
188  * @a: the amount to add to v...
189  * @u: ...unless v is equal to u.
190  *
191  * Atomically adds @a to @v, so long as it was not @u.
192  * Returns non-zero if @v was not @u, and zero otherwise.
193  */
194 static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
195 {
196         int c, old;
197         c = atomic_read(v);
198         for (;;) {
199                 if (unlikely(c == (u)))
200                         break;
201                 old = atomic_cmpxchg((v), c, c + (a));
202                 if (likely(old == c))
203                         break;
204                 c = old;
205         }
206         return c != (u);
207 }
208
209 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
210
211 /**
212  * atomic64_add_unless - add unless the number is a given value
213  * @v: pointer of type atomic64_t
214  * @a: the amount to add to v...
215  * @u: ...unless v is equal to u.
216  *
217  * Atomically adds @a to @v, so long as it was not @u.
218  * Returns non-zero if @v was not @u, and zero otherwise.
219  */
220 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
221 {
222         long c, old;
223         c = atomic64_read(v);
224         for (;;) {
225                 if (unlikely(c == (u)))
226                         break;
227                 old = atomic64_cmpxchg((v), c, c + (a));
228                 if (likely(old == c))
229                         break;
230                 c = old;
231         }
232         return c != (u);
233 }
234
235 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
236
237 #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
238 #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
239
240 #define atomic_dec_return(v) atomic_sub_return(1,(v))
241 #define atomic64_dec_return(v) atomic64_sub_return(1,(v))
242
243 #define atomic_inc_return(v) atomic_add_return(1,(v))
244 #define atomic64_inc_return(v) atomic64_add_return(1,(v))
245
246 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
247 #define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
248
249 #define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
250 #define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
251
252 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
253 #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
254
255 #define atomic_inc(v) atomic_add(1,(v))
256 #define atomic64_inc(v) atomic64_add(1,(v))
257
258 #define atomic_dec(v) atomic_sub(1,(v))
259 #define atomic64_dec(v) atomic64_sub(1,(v))
260
261 #define smp_mb__before_atomic_dec()     smp_mb()
262 #define smp_mb__after_atomic_dec()      smp_mb()
263 #define smp_mb__before_atomic_inc()     smp_mb()
264 #define smp_mb__after_atomic_inc()      smp_mb()
265
266 #include <asm-generic/atomic.h>
267 #endif /* _ALPHA_ATOMIC_H */