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