00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef P99_ATOMIC_ARM_H
00015 #define P99_ATOMIC_ARM_H 1
00016
00017 #ifndef P99_ATOMIC_H
00018 # warning "never include this file directly, use p99_atomic.h, instead"
00019 #endif
00020
00021 #if !defined(__thumb__) && !defined(__thumb2__)
00022
00023
00024 p99_inline
00025 uint8_t p00_arm_ldrexb(uint8_t volatile*p00_ptr) {
00026 uint8_t p00_ret;
00027 __asm__ volatile ("ldrexb %0,[%1]\t@ load exclusive\n"
00028 : "=&r" (p00_ret)
00029 : "r" (p00_ptr)
00030 : "cc", "memory"
00031 );
00032 return p00_ret;
00033 }
00034
00035 p99_inline
00036 _Bool p00_arm_strexb(uint8_t volatile*p00_ptr, uint8_t p00_val) {
00037 uint32_t p00_ret;
00038 __asm__ volatile ("strexb %0,%1,[%2]\t@ store exclusive\n"
00039 : "=&r" (p00_ret)
00040 : "r" (p00_val), "r" (p00_ptr)
00041 : "cc", "memory"
00042 );
00043 return p00_ret;
00044 }
00045 p99_inline
00046 uint16_t p00_arm_ldrexh(uint16_t volatile*p00_ptr) {
00047 uint16_t p00_ret;
00048 __asm__ volatile ("ldrexh %0,[%1]\t@ load exclusive\n"
00049 : "=&r" (p00_ret)
00050 : "r" (p00_ptr)
00051 : "cc", "memory"
00052 );
00053 return p00_ret;
00054 }
00055
00056 p99_inline
00057 _Bool p00_arm_strexh(uint16_t volatile*p00_ptr, uint16_t p00_val) {
00058 uint32_t p00_ret;
00059 __asm__ volatile ("strexh %0,%1,[%2]\t@ store exclusive\n"
00060 : "=&r" (p00_ret)
00061 : "r" (p00_val), "r" (p00_ptr)
00062 : "cc", "memory"
00063 );
00064 return p00_ret;
00065 }
00066 p99_inline
00067 uint32_t p00_arm_ldrex(uint32_t volatile*p00_ptr) {
00068 uint32_t p00_ret;
00069 __asm__ volatile ("ldrex %0,[%1]\t@ load exclusive\n"
00070 : "=&r" (p00_ret)
00071 : "r" (p00_ptr)
00072 : "cc", "memory"
00073 );
00074 return p00_ret;
00075 }
00076
00077 p99_inline
00078 _Bool p00_arm_strex(uint32_t volatile*p00_ptr, uint32_t p00_val) {
00079 uint32_t p00_ret;
00080 __asm__ volatile ("strex %0,%1,[%2]\t@ store exclusive\n"
00081 : "=&r" (p00_ret)
00082 : "r" (p00_val), "r" (p00_ptr)
00083 : "cc", "memory"
00084 );
00085 return p00_ret;
00086 }
00087 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
00088 p99_inline
00089 uint64_t p00_arm_ldrexd(uint64_t volatile*p00_ptr) {
00090 uint64_t p00_ret;
00091 __asm__ volatile ("ldrexd %0, %H0, [%1]\t@ load exclusive\n"
00092 : "=&r" (p00_ret)
00093 : "r" (p00_ptr)
00094 : "cc", "memory"
00095 );
00096 return p00_ret;
00097 }
00098
00099 p99_inline
00100 _Bool p00_arm_strex(uint64_t volatile*p00_ptr, uint64_t p00_val) {
00101 uint32_t p00_ret;
00102 __asm__ volatile ("strex %0, %1, %H1, [%2]\t@ store exclusive\n"
00103 : "=&r" (p00_ret)
00104 : "r" (p00_val), "r" (p00_ptr)
00105 : "cc", "memory"
00106 );
00107 return p00_ret;
00108 }
00109 # endif
00110 #else
00111
00112
00113 p99_inline
00114 uint8_t p00_arm_ldrexb(uint8_t volatile*p00_ptr) {
00115 uint8_t p00_ret;
00116 __asm__ volatile ("ldrexb %0,%1\t@ load exclusive\n"
00117 : "=&r" (p00_ret)
00118 : "m" (p00_ptr)
00119 : "cc", "memory"
00120 );
00121 return p00_ret;
00122 }
00123
00124 p99_inline
00125 _Bool p00_arm_strexb(uint8_t volatile*p00_ptr, uint8_t p00_val) {
00126 uint32_t p00_ret;
00127 __asm__ volatile ("strexb %0,%1,%2\t@ store exclusive\n"
00128 : "=&r" (p00_ret)
00129 : "r" (p00_val), "m" (p00_ptr)
00130 : "cc", "memory"
00131 );
00132 return p00_ret;
00133 }
00134 p99_inline
00135 uint16_t p00_arm_ldrexh(uint16_t volatile*p00_ptr) {
00136 uint16_t p00_ret;
00137 __asm__ volatile ("ldrexh %0,%1\t@ load exclusive\n"
00138 : "=&r" (p00_ret)
00139 : "m" (p00_ptr)
00140 : "cc", "memory"
00141 );
00142 return p00_ret;
00143 }
00144
00145 p99_inline
00146 _Bool p00_arm_strexh(uint16_t volatile*p00_ptr, uint16_t p00_val) {
00147 uint32_t p00_ret;
00148 __asm__ volatile ("strexh %0,%1,%2\t@ store exclusive\n"
00149 : "=&r" (p00_ret)
00150 : "r" (p00_val), "m" (p00_ptr)
00151 : "cc", "memory"
00152 );
00153 return p00_ret;
00154 }
00155 p99_inline
00156 uint32_t p00_arm_ldrex(uint32_t volatile*p00_ptr) {
00157 uint32_t p00_ret;
00158 __asm__ volatile ("ldrex %0,%1\t@ load exclusive\n"
00159 : "=&r" (p00_ret)
00160 : "m" (p00_ptr)
00161 : "cc", "memory"
00162 );
00163 return p00_ret;
00164 }
00165
00166 p99_inline
00167 _Bool p00_arm_strex(uint32_t volatile*p00_ptr, uint32_t p00_val) {
00168 uint32_t p00_ret;
00169 __asm__ volatile ("strex %0,%1,%2\t@ store exclusive\n"
00170 : "=&r" (p00_ret)
00171 : "r" (p00_val), "m" (p00_ptr)
00172 : "cc", "memory"
00173 );
00174 return p00_ret;
00175 }
00176 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
00177 p99_inline
00178 uint64_t p00_arm_ldrexd(uint64_t volatile*p00_ptr) {
00179 uint64_t p00_ret;
00180 __asm__ volatile ("ldrexd %0, %H0, %1\t@ load exclusive\n"
00181 : "=&r" (p00_ret)
00182 : "m" (p00_ptr)
00183 : "cc", "memory"
00184 );
00185 return p00_ret;
00186 }
00187
00188 p99_inline
00189 _Bool p00_arm_strexd(uint64_t volatile*p00_ptr, uint64_t p00_val) {
00190 uint32_t p00_ret;
00191 __asm__ volatile ("strexd %0, %1, %H1, %2\t@ store exclusive\n"
00192 : "=&r" (p00_ret)
00193 : "r" (p00_val), "m" (p00_ptr)
00194 : "cc", "memory"
00195 );
00196 return p00_ret;
00197 }
00198 # endif
00199 #endif
00200
00201 p99_inline
00202 uint8_t p00_atomic_exchange_1(uint8_t volatile* p00_objp, uint8_t p00_des) {
00203 for (;;) {
00204 uint8_t p00_ret = p00_arm_ldrexb(object);
00205 if (!p00_arm_strexb(object, p00_des)) return p00_ret;
00206 }
00207 }
00208
00209 p99_inline
00210 uint16_t p00_atomic_exchange_2(uint16_t volatile* p00_objp, uint16_t p00_des) {
00211 for (;;) {
00212 uint16_t p00_ret = p00_arm_ldrexh(object);
00213 if (!p00_arm_strexh(object, p00_des)) return p00_ret;
00214 }
00215 }
00216
00217 p99_inline
00218 uint32_t p00_atomic_exchange_4(uint32_t volatile* p00_objp, uint32_t p00_des) {
00219 for (;;) {
00220 uint32_t p00_ret = p00_arm_ldrex(object);
00221 if (!p00_arm_strex(object, p00_des)) return p00_ret;
00222 }
00223 }
00224
00225 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(P00_DOXYGEN)
00226 p99_inline
00227 uint64_t p00_atomic_exchange_8(uint64_t volatile* p00_objp, uint64_t p00_des) {
00228 for (;;) {
00229 uint64_t p00_ret = p00_arm_ldrexd(object);
00230 if (!p00_arm_strexd(object, p00_des)) return p00_ret;
00231 }
00232 }
00233 #endif
00234
00235 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && !defined(P00_DOXYGEN)
00236
00237 p99_inline
00238 uint32_t p00_sync_lock_test_and_set(uint32_t volatile *p00_objp) {
00239 return __sync_lock_test_and_set(p00_objp, 1);
00240 }
00241
00242 p99_inline
00243 void p00_sync_lock_release(uint32_t volatile *p00_objp) {
00244 __sync_lock_release(p00_objp);
00245 }
00246
00247 p99_inline
00248 void p00_mfence(void) {
00249 __sync_synchronize();
00250 }
00251
00252
00253 #else
00254
00281 p99_inline
00282 uint32_t p00_sync_lock_test_and_set(uint32_t volatile *object) {
00283 for (;;) {
00284 uint32_t p00_ret = p00_arm_ldrex(object);
00285
00286
00287
00288
00289
00290 if (!p00_arm_strex(object, 1) || p00_ret) return p00_ret;
00291 }
00292 }
00293
00294 p99_inline
00295 void p00_sync_lock_release(uint32_t volatile *object) {
00296 __sync_lock_release(object);
00297 }
00298
00299 p99_inline
00300 void p00_mfence(void) {
00301 __asm__ __volatile__("dmb":::"memory");
00302 }
00303
00304 p99_inline
00305 uint32_t __sync_val_compare_and_swap_4(uint32_t volatile *object, uint32_t p00_pre, uint32_t p00_des) {
00306 uint32_t p00_ret = 0;
00307 for (;;) {
00308 p00_ret = p00_arm_ldrex(object);
00309 if (p00_pre != p00_ret) {
00310
00311 p00_arm_strex(object, p00_ret);
00312 break;
00313 } else {
00314 if (!p00_arm_strex(object, p00_des)) break;
00315
00316 }
00317 }
00318 return p00_ret;
00319 }
00320
00321 p99_inline
00322 uint32_t __sync_fetch_and_add_4(uint32_t volatile *object, uint32_t p00_val) {
00323 uint32_t p00_ret = 0;
00324 for (;;) {
00325 p00_ret = p00_arm_ldrex(object);
00326 uint32_t p00_des = p00_ret + p00_val;
00327 if (!p00_arm_strex(object, p00_des)) break;
00328
00329 }
00330 return p00_ret;
00331 }
00332
00333 p99_inline
00334 uint32_t __sync_fetch_and_sub_4(uint32_t volatile *object, uint32_t p00_val) {
00335 uint32_t p00_ret = 0;
00336 for (;;) {
00337 p00_ret = p00_arm_ldrex(object);
00338 uint32_t p00_des = p00_ret - p00_val;
00339 if (!p00_arm_strex(object, p00_des)) break;
00340
00341 }
00342 return p00_ret;
00343 }
00344
00345 p99_inline
00346 uint32_t __sync_fetch_and_or_4(uint32_t volatile *object, uint32_t p00_val) {
00347 uint32_t p00_ret = 0;
00348 for (;;) {
00349 p00_ret = p00_arm_ldrex(object);
00350 uint32_t p00_des = p00_ret | p00_val;
00351 if (!p00_arm_strex(object, p00_des)) break;
00352
00353 }
00354 return p00_ret;
00355 }
00356
00357 p99_inline
00358 uint32_t __sync_fetch_and_and_4(uint32_t volatile *object, uint32_t p00_val) {
00359 uint32_t p00_ret = 0;
00360 for (;;) {
00361 p00_ret = p00_arm_ldrex(object);
00362 uint32_t p00_des = p00_ret & p00_val;
00363 if (!p00_arm_strex(object, p00_des)) break;
00364
00365 }
00366 return p00_ret;
00367 }
00368
00369 p99_inline
00370 uint32_t __sync_fetch_and_xor_4(uint32_t volatile *object, uint32_t p00_val) {
00371 uint32_t p00_ret = 0;
00372 for (;;) {
00373 p00_ret = p00_arm_ldrex(object);
00374 uint32_t p00_des = p00_ret ^ p00_val;
00375 if (!p00_arm_strex(object, p00_des)) break;
00376
00377 }
00378 return p00_ret;
00379 }
00380
00381 #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
00382 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
00383
00384
00389 # endif
00390
00391 #endif