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