#pragma once #define ASM_LABEL(i) #i ":\n\t" #define ATOMIC_LOAD(PRE, POST) \ atomic_word res; \ __asm__ __volatile__ \ ( \ PRE \ "ldr %0, %1\n\t" \ POST \ : "=r" (res) \ : "m" (*p) \ : "memory" \ ); \ return res; #define ATOMIC_LOAD2(PRE, POST) \ atomic_word2 ret; \ atomic_word res; \ __asm__ __volatile__ \ ( \ PRE \ "ldr %0, %1\n\t" \ POST \ : "=r" (res) \ : "m" (*p) \ : "memory" \ ); \ ret.v = res; \ return ret; #define ATOMIC_STORE(PRE, POST) \ __asm__ __volatile__ \ ( \ PRE \ "str %1, %0\n\t" \ POST \ : "=m" (*p) \ : "r" (v) \ : "memory" \ ); #define ATOMIC_XCHG(PRE, POST) \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "cc", "memory" \ ); \ return res; #define ATOMIC_XCHG2(PRE, POST) \ atomic_word2 ret; \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "cc", "memory" \ ); \ ret.v = res; \ return ret; static inline void atomic_thread_fence(int) { __sync_synchronize(); } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int) { ATOMIC_LOAD("", "") } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, int) { ATOMIC_STORE("", "") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, int) { ATOMIC_XCHG("", "") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return __sync_val_compare_and_swap(p, oldval, newval); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return __sync_val_compare_and_swap(p, oldval, newval); } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word *p, atomic_word val, int) { return __sync_fetch_and_add(p, val); } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word *p, atomic_word val, int) { return __sync_fetch_and_add(p, -val); } /* * extensions */ static inline void atomic_retain(volatile int *p) { __sync_fetch_and_add(p, 1); } static inline bool atomic_release(volatile int *p) { return __sync_fetch_and_add(p, -1) == 1; } // double word static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, int) { ATOMIC_LOAD2("", "") } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, int) { ATOMIC_STORE("", "") } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 v, int) { ATOMIC_XCHG2("", "") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int, int) { return __sync_val_compare_and_swap(&p->v, &oldval->v, newval.v); }