ExtendedAtomicOps.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #pragma once
  2. #define ASM_LABEL(i) #i ":\n\t"
  3. #define ATOMIC_LOAD(PRE, POST) \
  4. atomic_word res; \
  5. __asm__ __volatile__ \
  6. ( \
  7. PRE \
  8. "ldr %0, %1\n\t" \
  9. POST \
  10. : "=r" (res) \
  11. : "m" (*p) \
  12. : "memory" \
  13. ); \
  14. return res;
  15. #define ATOMIC_LOAD2(PRE, POST) \
  16. atomic_word2 ret; \
  17. atomic_word res; \
  18. __asm__ __volatile__ \
  19. ( \
  20. PRE \
  21. "ldr %0, %1\n\t" \
  22. POST \
  23. : "=r" (res) \
  24. : "m" (*p) \
  25. : "memory" \
  26. ); \
  27. ret.v = res; \
  28. return ret;
  29. #define ATOMIC_STORE(PRE, POST) \
  30. __asm__ __volatile__ \
  31. ( \
  32. PRE \
  33. "str %1, %0\n\t" \
  34. POST \
  35. : "=m" (*p) \
  36. : "r" (v) \
  37. : "memory" \
  38. );
  39. #define ATOMIC_XCHG(PRE, POST) \
  40. atomic_word res; \
  41. atomic_word success; \
  42. __asm__ __volatile__ \
  43. ( \
  44. PRE \
  45. ASM_LABEL (0) \
  46. "ldrex %2, [%4]\n\t" \
  47. "strex %0, %3, [%4]\n\t" \
  48. "teq %0, #0\n\t" \
  49. "bne 0b\n\t" \
  50. POST \
  51. : "=&r" (success), "+m" (*p), "=&r" (res) \
  52. : "r" (v), "r" (p) \
  53. : "cc", "memory" \
  54. ); \
  55. return res;
  56. #define ATOMIC_XCHG2(PRE, POST) \
  57. atomic_word2 ret; \
  58. atomic_word res; \
  59. atomic_word success; \
  60. __asm__ __volatile__ \
  61. ( \
  62. PRE \
  63. ASM_LABEL (0) \
  64. "ldrex %2, [%4]\n\t" \
  65. "strex %0, %3, [%4]\n\t" \
  66. "teq %0, #0\n\t" \
  67. "bne 0b\n\t" \
  68. POST \
  69. : "=&r" (success), "+m" (*p), "=&r" (res) \
  70. : "r" (v), "r" (p) \
  71. : "cc", "memory" \
  72. ); \
  73. ret.v = res; \
  74. return ret;
  75. static inline void atomic_thread_fence(int)
  76. {
  77. __sync_synchronize();
  78. }
  79. static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int)
  80. {
  81. ATOMIC_LOAD("", "")
  82. }
  83. static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, int)
  84. {
  85. ATOMIC_STORE("", "")
  86. }
  87. static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, int)
  88. {
  89. ATOMIC_XCHG("", "")
  90. }
  91. static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int)
  92. {
  93. return __sync_val_compare_and_swap(p, oldval, newval);
  94. }
  95. static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int)
  96. {
  97. return __sync_val_compare_and_swap(p, oldval, newval);
  98. }
  99. static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word *p, atomic_word val, int)
  100. {
  101. return __sync_fetch_and_add(p, val);
  102. }
  103. static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word *p, atomic_word val, int)
  104. {
  105. return __sync_fetch_and_add(p, -val);
  106. }
  107. /*
  108. * extensions
  109. */
  110. static inline void atomic_retain(volatile int *p)
  111. {
  112. __sync_fetch_and_add(p, 1);
  113. }
  114. static inline bool atomic_release(volatile int *p)
  115. {
  116. return __sync_fetch_and_add(p, -1) == 1;
  117. }
  118. // double word
  119. static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, int)
  120. {
  121. ATOMIC_LOAD2("", "")
  122. }
  123. static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, int)
  124. {
  125. ATOMIC_STORE("", "")
  126. }
  127. static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 v, int)
  128. {
  129. ATOMIC_XCHG2("", "")
  130. }
  131. static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int, int)
  132. {
  133. return __sync_val_compare_and_swap(&p->v, &oldval->v, newval.v);
  134. }