]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - include/asm-powerpc/atomic.h
c5b12fd2b46bf149486245b14da0dde5fef32bb2
[karo-tx-linux.git] / include / asm-powerpc / atomic.h
1 #ifndef _ASM_POWERPC_ATOMIC_H_
2 #define _ASM_POWERPC_ATOMIC_H_
3
4 /*
5  * PowerPC atomic operations
6  */
7
8 typedef struct { volatile int counter; } atomic_t;
9
10 #ifdef __KERNEL__
11 #include <asm/synch.h>
12 #include <asm/asm-compat.h>
13
14 #define ATOMIC_INIT(i)          { (i) }
15
16 #define atomic_read(v)          ((v)->counter)
17 #define atomic_set(v,i)         (((v)->counter) = (i))
18
19 static __inline__ void atomic_add(int a, atomic_t *v)
20 {
21         int t;
22
23         __asm__ __volatile__(
24 "1:     lwarx   %0,0,%3         # atomic_add\n\
25         add     %0,%2,%0\n"
26         PPC405_ERR77(0,%3)
27 "       stwcx.  %0,0,%3 \n\
28         bne-    1b"
29         : "=&r" (t), "=m" (v->counter)
30         : "r" (a), "r" (&v->counter), "m" (v->counter)
31         : "cc");
32 }
33
34 static __inline__ int atomic_add_return(int a, atomic_t *v)
35 {
36         int t;
37
38         __asm__ __volatile__(
39         EIEIO_ON_SMP
40 "1:     lwarx   %0,0,%2         # atomic_add_return\n\
41         add     %0,%1,%0\n"
42         PPC405_ERR77(0,%2)
43 "       stwcx.  %0,0,%2 \n\
44         bne-    1b"
45         ISYNC_ON_SMP
46         : "=&r" (t)
47         : "r" (a), "r" (&v->counter)
48         : "cc", "memory");
49
50         return t;
51 }
52
53 #define atomic_add_negative(a, v)       (atomic_add_return((a), (v)) < 0)
54
55 static __inline__ void atomic_sub(int a, atomic_t *v)
56 {
57         int t;
58
59         __asm__ __volatile__(
60 "1:     lwarx   %0,0,%3         # atomic_sub\n\
61         subf    %0,%2,%0\n"
62         PPC405_ERR77(0,%3)
63 "       stwcx.  %0,0,%3 \n\
64         bne-    1b"
65         : "=&r" (t), "=m" (v->counter)
66         : "r" (a), "r" (&v->counter), "m" (v->counter)
67         : "cc");
68 }
69
70 static __inline__ int atomic_sub_return(int a, atomic_t *v)
71 {
72         int t;
73
74         __asm__ __volatile__(
75         EIEIO_ON_SMP
76 "1:     lwarx   %0,0,%2         # atomic_sub_return\n\
77         subf    %0,%1,%0\n"
78         PPC405_ERR77(0,%2)
79 "       stwcx.  %0,0,%2 \n\
80         bne-    1b"
81         ISYNC_ON_SMP
82         : "=&r" (t)
83         : "r" (a), "r" (&v->counter)
84         : "cc", "memory");
85
86         return t;
87 }
88
89 static __inline__ void atomic_inc(atomic_t *v)
90 {
91         int t;
92
93         __asm__ __volatile__(
94 "1:     lwarx   %0,0,%2         # atomic_inc\n\
95         addic   %0,%0,1\n"
96         PPC405_ERR77(0,%2)
97 "       stwcx.  %0,0,%2 \n\
98         bne-    1b"
99         : "=&r" (t), "=m" (v->counter)
100         : "r" (&v->counter), "m" (v->counter)
101         : "cc");
102 }
103
104 static __inline__ int atomic_inc_return(atomic_t *v)
105 {
106         int t;
107
108         __asm__ __volatile__(
109         EIEIO_ON_SMP
110 "1:     lwarx   %0,0,%1         # atomic_inc_return\n\
111         addic   %0,%0,1\n"
112         PPC405_ERR77(0,%1)
113 "       stwcx.  %0,0,%1 \n\
114         bne-    1b"
115         ISYNC_ON_SMP
116         : "=&r" (t)
117         : "r" (&v->counter)
118         : "cc", "memory");
119
120         return t;
121 }
122
123 /*
124  * atomic_inc_and_test - increment and test
125  * @v: pointer of type atomic_t
126  *
127  * Atomically increments @v by 1
128  * and returns true if the result is zero, or false for all
129  * other cases.
130  */
131 #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
132
133 static __inline__ void atomic_dec(atomic_t *v)
134 {
135         int t;
136
137         __asm__ __volatile__(
138 "1:     lwarx   %0,0,%2         # atomic_dec\n\
139         addic   %0,%0,-1\n"
140         PPC405_ERR77(0,%2)\
141 "       stwcx.  %0,0,%2\n\
142         bne-    1b"
143         : "=&r" (t), "=m" (v->counter)
144         : "r" (&v->counter), "m" (v->counter)
145         : "cc");
146 }
147
148 static __inline__ int atomic_dec_return(atomic_t *v)
149 {
150         int t;
151
152         __asm__ __volatile__(
153         EIEIO_ON_SMP
154 "1:     lwarx   %0,0,%1         # atomic_dec_return\n\
155         addic   %0,%0,-1\n"
156         PPC405_ERR77(0,%1)
157 "       stwcx.  %0,0,%1\n\
158         bne-    1b"
159         ISYNC_ON_SMP
160         : "=&r" (t)
161         : "r" (&v->counter)
162         : "cc", "memory");
163
164         return t;
165 }
166
167 #define atomic_sub_and_test(a, v)       (atomic_sub_return((a), (v)) == 0)
168 #define atomic_dec_and_test(v)          (atomic_dec_return((v)) == 0)
169
170 /*
171  * Atomically test *v and decrement if it is greater than 0.
172  * The function returns the old value of *v minus 1.
173  */
174 static __inline__ int atomic_dec_if_positive(atomic_t *v)
175 {
176         int t;
177
178         __asm__ __volatile__(
179         EIEIO_ON_SMP
180 "1:     lwarx   %0,0,%1         # atomic_dec_if_positive\n\
181         addic.  %0,%0,-1\n\
182         blt-    2f\n"
183         PPC405_ERR77(0,%1)
184 "       stwcx.  %0,0,%1\n\
185         bne-    1b"
186         ISYNC_ON_SMP
187         "\n\
188 2:"     : "=&r" (t)
189         : "r" (&v->counter)
190         : "cc", "memory");
191
192         return t;
193 }
194
195 #define smp_mb__before_atomic_dec()     smp_mb()
196 #define smp_mb__after_atomic_dec()      smp_mb()
197 #define smp_mb__before_atomic_inc()     smp_mb()
198 #define smp_mb__after_atomic_inc()      smp_mb()
199
200 #endif /* __KERNEL__ */
201 #endif /* _ASM_POWERPC_ATOMIC_H_ */