00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #ifndef _atomic_ppc_h
00048 #define _atomic_ppc_h
00049
00050 #define HAVE_ASM_INLINE_ATOMIC_OPS
00051 #define HAVE_ASM_INLINE_MEMBAR
00052
00053 #ifdef __CPU_ppc64
00054 #warning powerpc64 atomic code was not tested, please report problems to \
00055 serdev@iptel.org or andrei@iptel.org
00056 #endif
00057
00058
00059 #ifdef NOSMP
00060 #define membar() asm volatile ("" : : : "memory")
00061 #define membar_read() membar()
00062 #define membar_write() membar()
00063 #define membar_depends() do {} while(0)
00064
00065
00066 #define membar_enter_lock() do {} while(0)
00067 #define membar_leave_lock() do {} while(0)
00068
00069
00070
00071
00072
00073 #define membar_atomic_op() membar()
00074 #define membar_atomic_setget() membar()
00075 #define membar_write_atomic_op() membar_write()
00076 #define membar_write_atomic_setget() membar_write()
00077 #define membar_read_atomic_op() membar_read()
00078 #define membar_read_atomic_setget() membar_read()
00079
00080 #else
00081 #define membar() asm volatile ("sync \n\t" : : : "memory")
00082
00083 #define membar_read() asm volatile ("lwsync \n\t" : : : "memory")
00084
00085 #define membar_write() asm volatile ("eieio \n\t" : : : "memory")
00086 #define membar_depends() do {} while(0)
00087 #define membar_enter_lock() asm volatile("lwsync \n\t" : : : "memory")
00088
00089
00090 #define membar_leave_lock() asm volatile("lwsync \n\t" : : : "memory")
00091
00092
00093
00094
00095
00096 #define membar_atomic_op() membar()
00097 #define membar_atomic_setget() membar()
00098 #define membar_write_atomic_op() membar_write()
00099 #define membar_write_atomic_setget() membar_write()
00100 #define membar_read_atomic_op() membar_read()
00101 #define membar_read_atomic_setget() membar_read()
00102 #endif
00103
00104
00105 #define ATOMIC_ASM_OP0_int(op) \
00106 "1: lwarx %0, 0, %2 \n\t" \
00107 " " op " \n\t" \
00108 " stwcx. %0, 0, %2 \n\t" \
00109 " bne- 1b \n\t"
00110
00111 #define ATOMIC_ASM_OP3_int(op) \
00112 "1: lwarx %0, 0, %2 \n\t" \
00113 " " op " \n\t" \
00114 " stwcx. %3, 0, %2 \n\t" \
00115 " bne- 1b \n\t" \
00116 "2: \n\t"
00117
00118 #ifdef __CPU_ppc64
00119 #define ATOMIC_ASM_OP0_long(op) \
00120 "1: ldarx %0, 0, %2 \n\t" \
00121 " " op " \n\t" \
00122 " stdcx. %0, 0, %2 \n\t" \
00123 " bne- 1b \n\t"
00124
00125 #define ATOMIC_ASM_OP3_long(op) \
00126 "1: ldarx %0, 0, %2 \n\t" \
00127 " " op " \n\t" \
00128 " stdcx. %3, 0, %2 \n\t" \
00129 " bne- 1b \n\t" \
00130 "2: \n\t"
00131
00132 #else
00133 #define ATOMIC_ASM_OP0_long ATOMIC_ASM_OP0_int
00134 #define ATOMIC_ASM_OP3_long ATOMIC_ASM_OP3_int
00135 #endif
00136
00137
00138 #define ATOMIC_FUNC_DECL(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
00139 inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var) \
00140 { \
00141 P_TYPE ret; \
00142 asm volatile( \
00143 ATOMIC_ASM_OP0_##P_TYPE(OP) \
00144 : "=&r"(ret), "=m"(*var) : "r"(var) : "cc" \
00145 ); \
00146 return RET_EXPR; \
00147 }
00148
00149
00150 #define ATOMIC_FUNC_DECL1(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
00151 inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
00152 P_TYPE v) \
00153 { \
00154 P_TYPE ret; \
00155 asm volatile( \
00156 ATOMIC_ASM_OP0_##P_TYPE(OP) \
00157 : "=&r"(ret), "=m"(*var) : "r"(var), "r"(v) : "cc" \
00158 ); \
00159 return RET_EXPR; \
00160 }
00161
00162
00163 #define ATOMIC_FUNC_DECL3(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
00164 inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
00165 P_TYPE v) \
00166 { \
00167 P_TYPE ret; \
00168 asm volatile( \
00169 ATOMIC_ASM_OP3_##P_TYPE(OP) \
00170 : "=&r"(ret), "=m"(*var) : "r"(var), "r"(v) : "cc" \
00171 ); \
00172 return RET_EXPR; \
00173 }
00174
00175
00176 #define ATOMIC_CMPXCHG_DECL(NAME, P_TYPE) \
00177 inline static P_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
00178 P_TYPE old, \
00179 P_TYPE new_v) \
00180 { \
00181 P_TYPE ret; \
00182 asm volatile( \
00183 ATOMIC_ASM_OP3_##P_TYPE("cmpw %0, %4 \n\t bne- 2f") \
00184 : "=&r"(ret), "=m"(*var) : "r"(var), "r"(new_v), "r"(old) \
00185 : "cc" \
00186 ); \
00187 return ret; \
00188 }
00189
00190
00191
00192
00193
00194 ATOMIC_FUNC_DECL(inc, "addic %0, %0, 1", int, void, )
00195 ATOMIC_FUNC_DECL(dec, "addic %0, %0, -1", int, void, )
00196 ATOMIC_FUNC_DECL1(and, "and %0, %0, %3", int, void, )
00197 ATOMIC_FUNC_DECL1(or, "or %0, %0, %3", int, void, )
00198 ATOMIC_FUNC_DECL(inc_and_test, "addic %0, %0, 1", int, int, (ret==0) )
00199 ATOMIC_FUNC_DECL(dec_and_test, "addic %0, %0, -1", int, int, (ret==0) )
00200 ATOMIC_FUNC_DECL3(get_and_set, , int, int, ret)
00201 ATOMIC_CMPXCHG_DECL(cmpxchg, int)
00202 ATOMIC_FUNC_DECL1(add, "add %0, %0, %3" , int, int, ret)
00203
00204 ATOMIC_FUNC_DECL(inc, "addic %0, %0, 1", long, void, )
00205 ATOMIC_FUNC_DECL(dec, "addic %0, %0, -1", long, void, )
00206 ATOMIC_FUNC_DECL1(and, "and %0, %0, %3",long, void, )
00207 ATOMIC_FUNC_DECL1(or, "or %0, %0, %3", long, void, )
00208 ATOMIC_FUNC_DECL(inc_and_test, "addic %0, %0, 1", long, long, (ret==0) )
00209 ATOMIC_FUNC_DECL(dec_and_test, "addic %0, %0, -1", long, long, (ret==0) )
00210 ATOMIC_FUNC_DECL3(get_and_set, , long, long, ret)
00211 ATOMIC_CMPXCHG_DECL(cmpxchg, long)
00212 ATOMIC_FUNC_DECL1(add, "add %0, %0, %3" , long, long, ret)
00213
00214
00215 #define atomic_inc(var) atomic_inc_int(&(var)->val)
00216 #define atomic_dec(var) atomic_dec_int(&(var)->val)
00217 #define atomic_and(var, mask) atomic_and_int(&(var)->val, (mask))
00218 #define atomic_or(var, mask) atomic_or_int(&(var)->val, (mask))
00219 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
00220 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
00221 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
00222 #define atomic_cmpxchg(var, o, n) atomic_cmpxchg_int(&(var)->val, (o), (n))
00223 #define atomic_add(var, i) atomic_add_int(&(var)->val, (i))
00224
00225
00226
00227
00228 #define mb_atomic_set_int(v, i) \
00229 do{ \
00230 membar(); \
00231 atomic_set_int(v, i); \
00232 }while(0)
00233
00234
00235
00236 inline static int mb_atomic_get_int(volatile int* v)
00237 {
00238 membar();
00239 return atomic_get_int(v);
00240 }
00241
00242
00243 #define mb_atomic_inc_int(v) \
00244 do{ \
00245 membar(); \
00246 atomic_inc_int(v); \
00247 }while(0)
00248
00249 #define mb_atomic_dec_int(v) \
00250 do{ \
00251 membar(); \
00252 atomic_dec_int(v); \
00253 }while(0)
00254
00255 #define mb_atomic_or_int(v, m) \
00256 do{ \
00257 membar(); \
00258 atomic_or_int(v, m); \
00259 }while(0)
00260
00261 #define mb_atomic_and_int(v, m) \
00262 do{ \
00263 membar(); \
00264 atomic_and_int(v, m); \
00265 }while(0)
00266
00267 inline static int mb_atomic_inc_and_test_int(volatile int* v)
00268 {
00269 membar();
00270 return atomic_inc_and_test_int(v);
00271 }
00272
00273 inline static int mb_atomic_dec_and_test_int(volatile int* v)
00274 {
00275 membar();
00276 return atomic_dec_and_test_int(v);
00277 }
00278
00279
00280 inline static int mb_atomic_get_and_set_int(volatile int* v, int i)
00281 {
00282 membar();
00283 return atomic_get_and_set_int(v, i);
00284 }
00285
00286 inline static int mb_atomic_cmpxchg_int(volatile int* v, int o, int n)
00287 {
00288 membar();
00289 return atomic_cmpxchg_int(v, o, n);
00290 }
00291
00292 inline static int mb_atomic_add_int(volatile int* v, int i)
00293 {
00294 membar();
00295 return atomic_add_int(v, i);
00296 }
00297
00298
00299 #define mb_atomic_set_long(v, i) \
00300 do{ \
00301 membar(); \
00302 atomic_set_long(v, i); \
00303 }while(0)
00304
00305
00306
00307 inline static long mb_atomic_get_long(volatile long* v)
00308 {
00309 membar();
00310 return atomic_get_long(v);
00311 }
00312
00313
00314 #define mb_atomic_inc_long(v) \
00315 do{ \
00316 membar(); \
00317 atomic_inc_long(v); \
00318 }while(0)
00319
00320
00321 #define mb_atomic_dec_long(v) \
00322 do{ \
00323 membar(); \
00324 atomic_dec_long(v); \
00325 }while(0)
00326
00327 #define mb_atomic_or_long(v, m) \
00328 do{ \
00329 membar(); \
00330 atomic_or_long(v, m); \
00331 }while(0)
00332
00333 #define mb_atomic_and_long(v, m) \
00334 do{ \
00335 membar(); \
00336 atomic_and_long(v, m); \
00337 }while(0)
00338
00339 inline static long mb_atomic_inc_and_test_long(volatile long* v)
00340 {
00341 membar();
00342 return atomic_inc_and_test_long(v);
00343 }
00344
00345 inline static long mb_atomic_dec_and_test_long(volatile long* v)
00346 {
00347 membar();
00348 return atomic_dec_and_test_long(v);
00349 }
00350
00351
00352 inline static long mb_atomic_get_and_set_long(volatile long* v, long l)
00353 {
00354 membar();
00355 return atomic_get_and_set_long(v, l);
00356 }
00357
00358 inline static long mb_atomic_cmpxchg_long(volatile long* v, long o, long n)
00359 {
00360 membar();
00361 return atomic_cmpxchg_long(v, o, n);
00362 }
00363
00364 inline static long mb_atomic_add_long(volatile long* v, long i)
00365 {
00366 membar();
00367 return atomic_add_long(v, i);
00368 }
00369
00370
00371
00372 #define mb_atomic_inc(var) mb_atomic_inc_int(&(var)->val)
00373 #define mb_atomic_dec(var) mb_atomic_dec_int(&(var)->val)
00374 #define mb_atomic_and(var, mask) mb_atomic_and_int(&(var)->val, (mask))
00375 #define mb_atomic_or(var, mask) mb_atomic_or_int(&(var)->val, (mask))
00376 #define mb_atomic_dec_and_test(var) mb_atomic_dec_and_test_int(&(var)->val)
00377 #define mb_atomic_inc_and_test(var) mb_atomic_inc_and_test_int(&(var)->val)
00378 #define mb_atomic_get(var) mb_atomic_get_int(&(var)->val)
00379 #define mb_atomic_set(var, i) mb_atomic_set_int(&(var)->val, i)
00380 #define mb_atomic_get_and_set(var, i) mb_atomic_get_and_set_int(&(var)->val, i)
00381 #define mb_atomic_cmpxchg(v, o, n) atomic_cmpxchg_int(&(v)->val, o, n)
00382 #define mb_atomic_add(v, a) atomic_add_int(&(v)->val, a)
00383
00384
00385 #endif