123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- #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);
- }
|