00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef __ARCH_powerpc_ORO_ATOMIC__
00040 #define __ARCH_powerpc_ORO_ATOMIC__
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #ifdef _cplusplus
00052 extern "C"
00053 {
00054 #endif // _cplusplus
00055
00056 #ifdef __SUBARCH_HAS_LWSYNC
00057 # define LWSYNC lwsync
00058 #else
00059 # define LWSYNC sync
00060 #endif
00061
00062 #define ISYNC_ON_SMP
00063 #define LWSYNC_ON_SMP
00064
00065 static inline void eieio(void)
00066 {
00067 __asm__ __volatile__ ("eieio" : : : "memory");
00068 }
00069
00070 static inline void isync(void)
00071 {
00072 __asm__ __volatile__ ("isync" : : : "memory");
00073 }
00074
00075
00076
00077
00078 #ifdef __ASSEMBLY__
00079 # define stringify_in_c(...) __VA_ARGS__
00080 # define ASM_CONST(x) x
00081 #else
00082
00083 # define __stringify_in_c(...) #__VA_ARGS__
00084 # define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " "
00085 # define __ASM_CONST(x) x##UL
00086 # define ASM_CONST(x) __ASM_CONST(x)
00087 #endif
00088
00089
00090 #define PPC_LL stringify_in_c(lwz)
00091 #define PPC_STL stringify_in_c(stw)
00092 #define PPC_LCMPI stringify_in_c(cmpwi)
00093 #define PPC_LONG stringify_in_c(.long)
00094 #define PPC_TLNEI stringify_in_c(twnei)
00095 #define PPC_LLARX stringify_in_c(lwarx)
00096 #define PPC_STLCX stringify_in_c(stwcx.)
00097 #define PPC_CNTLZL stringify_in_c(cntlzw)
00098
00099 #ifdef CONFIG_IBM405_ERR77
00100
00101
00102
00103 #define PPC405_ERR77(ra,rb) stringify_in_c(dcbt ra, rb;)
00104 #define PPC405_ERR77_SYNC stringify_in_c(sync;)
00105 #else
00106 #define PPC405_ERR77(ra,rb)
00107 #define PPC405_ERR77_SYNC
00108 #endif
00109
00110
00111
00112
00113
00114
00115
00116
00117 typedef struct { volatile int counter; } oro_atomic_t;
00118
00119 #define ORO_ATOMIC_INIT(i) { (i) }
00120 #define ORO_ATOMIC_SETUP oro_atomic_set
00121 #define ORO_ATOMIC_CLEANUP(v)
00122
00123 #define oro_atomic_read(v) ((v)->counter)
00124 #define oro_atomic_set(v,i) (((v)->counter) = (i))
00125
00126 static __inline__ void oro_atomic_add(oro_atomic_t *v, int n)
00127 {
00128 int t;
00129
00130 __asm__ __volatile__(
00131 "1: lwarx %0,0,%3 # oro_atomic_add\n\
00132 add %0,%2,%0\n"
00133 PPC405_ERR77(0,%3)
00134 " stwcx. %0,0,%3 \n\
00135 bne- 1b"
00136 : "=&r" (t), "=m" (v->counter)
00137 : "r" (a), "r" (&v->counter), "m" (v->counter)
00138 : "cc");
00139 }
00140
00141 static __inline__ int oro_atomic_add_return(oro_atomic_t *v, int n)
00142 {
00143 int t;
00144
00145 __asm__ __volatile__(
00146 LWSYNC_ON_SMP
00147 "1: lwarx %0,0,%2 # oro_atomic_add_return\n\
00148 add %0,%1,%0\n"
00149 PPC405_ERR77(0,%2)
00150 " stwcx. %0,0,%2 \n\
00151 bne- 1b"
00152 ISYNC_ON_SMP
00153 : "=&r" (t)
00154 : "r" (a), "r" (&v->counter)
00155 : "cc", "memory");
00156
00157 return t;
00158 }
00159
00160 #define oro_atomic_add_negative(a, v) (oro_atomic_add_return((a), (v)) < 0)
00161
00162 static __inline__ void oro_atomic_sub(int a, oro_atomic_t *v)
00163 {
00164 int t;
00165
00166 __asm__ __volatile__(
00167 "1: lwarx %0,0,%3 # oro_atomic_sub\n\
00168 subf %0,%2,%0\n"
00169 PPC405_ERR77(0,%3)
00170 " stwcx. %0,0,%3 \n\
00171 bne- 1b"
00172 : "=&r" (t), "=m" (v->counter)
00173 : "r" (a), "r" (&v->counter), "m" (v->counter)
00174 : "cc");
00175 }
00176
00177 static __inline__ int oro_atomic_sub_return(oro_atomic_t *v, int n)
00178 {
00179 int t;
00180
00181 __asm__ __volatile__(
00182 LWSYNC_ON_SMP
00183 "1: lwarx %0,0,%2 # oro_atomic_sub_return\n\
00184 subf %0,%1,%0\n"
00185 PPC405_ERR77(0,%2)
00186 " stwcx. %0,0,%2 \n\
00187 bne- 1b"
00188 ISYNC_ON_SMP
00189 : "=&r" (t)
00190 : "r" (a), "r" (&v->counter)
00191 : "cc", "memory");
00192
00193 return t;
00194 }
00195
00196 static __inline__ void oro_atomic_inc(oro_atomic_t *v)
00197 {
00198 int t;
00199
00200 __asm__ __volatile__(
00201 "1: lwarx %0,0,%2 # oro_atomic_inc\n\
00202 addic %0,%0,1\n"
00203 PPC405_ERR77(0,%2)
00204 " stwcx. %0,0,%2 \n\
00205 bne- 1b"
00206 : "=&r" (t), "=m" (v->counter)
00207 : "r" (&v->counter), "m" (v->counter)
00208 : "cc");
00209 }
00210
00211 static __inline__ int oro_atomic_inc_return(oro_atomic_t *v)
00212 {
00213 int t;
00214
00215 __asm__ __volatile__(
00216 LWSYNC_ON_SMP
00217 "1: lwarx %0,0,%1 # oro_atomic_inc_return\n\
00218 addic %0,%0,1\n"
00219 PPC405_ERR77(0,%1)
00220 " stwcx. %0,0,%1 \n\
00221 bne- 1b"
00222 ISYNC_ON_SMP
00223 : "=&r" (t)
00224 : "r" (&v->counter)
00225 : "cc", "memory");
00226
00227 return t;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 #define oro_atomic_inc_and_test(v) (oro_atomic_inc_return(v) == 0)
00239
00240 static __inline__ void oro_atomic_dec(oro_atomic_t *v)
00241 {
00242 int t;
00243
00244 __asm__ __volatile__(
00245 "1: lwarx %0,0,%2 # oro_atomic_dec\n\
00246 addic %0,%0,-1\n"
00247 PPC405_ERR77(0,%2)\
00248 " stwcx. %0,0,%2\n\
00249 bne- 1b"
00250 : "=&r" (t), "=m" (v->counter)
00251 : "r" (&v->counter), "m" (v->counter)
00252 : "cc");
00253 }
00254
00255 static __inline__ int oro_atomic_dec_return(oro_atomic_t *v)
00256 {
00257 int t;
00258
00259 __asm__ __volatile__(
00260 LWSYNC_ON_SMP
00261 "1: lwarx %0,0,%1 # oro_atomic_dec_return\n\
00262 addic %0,%0,-1\n"
00263 PPC405_ERR77(0,%1)
00264 " stwcx. %0,0,%1\n\
00265 bne- 1b"
00266 ISYNC_ON_SMP
00267 : "=&r" (t)
00268 : "r" (&v->counter)
00269 : "cc", "memory");
00270
00271 return t;
00272 }
00273
00274 #define oro_atomic_oro_cmpxchg(v, o, n) ((int)oro_cmpxchg(&((v)->counter), (o), (n)))
00275 #define oro_atomic_xchg(v, new) (xchg(&((v)->counter), new))
00276
00286 #define oro_atomic_add_unless(v, a, u) \
00287 ({ \
00288 int c, old; \
00289 c = oro_atomic_read(v); \
00290 for (;;) { \
00291 if (unlikely(c == (u))) \
00292 break; \
00293 old = oro_atomic_oro_cmpxchg((v), c, c + (a)); \
00294 if (likely(old == c)) \
00295 break; \
00296 c = old; \
00297 } \
00298 c != (u); \
00299 })
00300 #define oro_atomic_inc_not_zero(v) oro_atomic_add_unless((v), 1, 0)
00301
00302 #define oro_atomic_sub_and_test(a, v) (oro_atomic_sub_return((a), (v)) == 0)
00303 #define oro_atomic_dec_and_test(v) (oro_atomic_dec_return((v)) == 0)
00304
00305
00306
00307
00308
00309 static __inline__ int oro_atomic_dec_if_positive(oro_atomic_t *v)
00310 {
00311 int t;
00312
00313 __asm__ __volatile__(
00314 LWSYNC_ON_SMP
00315 "1: lwarx %0,0,%1 # oro_atomic_dec_if_positive\n\
00316 addic. %0,%0,-1\n\
00317 blt- 2f\n"
00318 PPC405_ERR77(0,%1)
00319 " stwcx. %0,0,%1\n\
00320 bne- 1b"
00321 ISYNC_ON_SMP
00322 "\n\
00323 2:" : "=&r" (t)
00324 : "r" (&v->counter)
00325 : "cc", "memory");
00326
00327 return t;
00328 }
00329
00330 #define smp_mb__before_oro_atomic_dec() smp_mb()
00331 #define smp_mb__after_oro_atomic_dec() smp_mb()
00332 #define smp_mb__before_oro_atomic_inc() smp_mb()
00333 #define smp_mb__after_oro_atomic_inc() smp_mb()
00334
00335 #undef ORO_LOCK
00336
00337 #ifdef _cplusplus
00338 }
00339 #endif // _cplusplus
00340
00341 #endif // __ARCH_powerpc_ORO_ATOMIC__
00342