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