Atomic.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #pragma once
  2. #include "c-api/il2cpp-config-platforms.h"
  3. #include <stdint.h>
  4. #include "utils/NonCopyable.h"
  5. #include "Baselib.h"
  6. #include "C/Baselib_Atomic_TypeSafe.h"
  7. namespace il2cpp
  8. {
  9. namespace os
  10. {
  11. class Atomic : public il2cpp::utils::NonCopyable
  12. {
  13. public:
  14. // All 32bit atomics must be performed on 4-byte aligned addresses. All 64bit atomics must be
  15. // performed on 8-byte aligned addresses.
  16. // Add and Add64 return the *result* of the addition, not the old value! (i.e. they work like
  17. // InterlockedAdd and __sync_add_and_fetch).
  18. static inline void FullMemoryBarrier()
  19. {
  20. Baselib_atomic_thread_fence_seq_cst();
  21. }
  22. static inline int32_t Add(int32_t* location1, int32_t value)
  23. {
  24. return Baselib_atomic_fetch_add_32_seq_cst(location1, value) + value;
  25. }
  26. static inline uint32_t Add(uint32_t* location1, uint32_t value)
  27. {
  28. return (uint32_t)Add((int32_t*)location1, (int32_t)value);
  29. }
  30. #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
  31. static inline int64_t Add64(int64_t* location1, int64_t value)
  32. {
  33. return Baselib_atomic_fetch_add_64_seq_cst(location1, value) + value;
  34. }
  35. #endif
  36. template<typename T>
  37. static inline T* CompareExchangePointer(T** dest, T* newValue, T* oldValue)
  38. {
  39. Baselib_atomic_compare_exchange_strong_ptr_seq_cst_seq_cst((intptr_t*)dest, (intptr_t*)&oldValue, (intptr_t)newValue);
  40. return static_cast<T*>(oldValue);
  41. }
  42. template<typename T>
  43. static inline T* ExchangePointer(T** dest, const T* newValue)
  44. {
  45. return (T*)Baselib_atomic_exchange_ptr_seq_cst((intptr_t*)dest, (intptr_t)newValue);
  46. }
  47. static inline int64_t Read64(int64_t* addr)
  48. {
  49. return Baselib_atomic_fetch_add_64_seq_cst(addr, 0);
  50. }
  51. static inline uint64_t Read64(uint64_t* addr)
  52. {
  53. return (uint64_t)Read64((int64_t*)addr);
  54. }
  55. static inline int32_t LoadRelaxed(const int32_t* addr)
  56. {
  57. return Baselib_atomic_load_32_relaxed(addr);
  58. }
  59. template<typename T>
  60. static inline T* LoadPointerRelaxed(const T* const * addr)
  61. {
  62. return (T*)Baselib_atomic_load_ptr_relaxed((const intptr_t*)addr);
  63. }
  64. template<typename T>
  65. static inline T* ReadPointer(T** pointer)
  66. {
  67. return (T*)Baselib_atomic_load_ptr_relaxed((intptr_t*)pointer);
  68. }
  69. template<typename T>
  70. static inline void PublishPointer(T** pointer, T* value)
  71. {
  72. Baselib_atomic_thread_fence_release();
  73. Baselib_atomic_store_ptr_relaxed((intptr_t*)pointer, (intptr_t)value);
  74. }
  75. static inline int32_t Increment(int32_t* value)
  76. {
  77. return Baselib_atomic_fetch_add_32_seq_cst(value, 1) + 1;
  78. }
  79. static inline uint32_t Increment(uint32_t* value)
  80. {
  81. return (uint32_t)Increment((int32_t*)value);
  82. }
  83. #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
  84. static inline int64_t Increment64(int64_t* value)
  85. {
  86. return Baselib_atomic_fetch_add_64_seq_cst(value, 1) + 1;
  87. }
  88. static inline uint64_t Increment64(uint64_t* value)
  89. {
  90. return (uint64_t)Increment64((int64_t*)value);
  91. }
  92. #endif
  93. static inline int32_t Decrement(int32_t* value)
  94. {
  95. return Baselib_atomic_fetch_add_32_seq_cst(value, -1) - 1;
  96. }
  97. static inline uint32_t Decrement(uint32_t* value)
  98. {
  99. return (uint32_t)Decrement((int32_t*)value);
  100. }
  101. #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
  102. static inline int64_t Decrement64(int64_t* value)
  103. {
  104. return Baselib_atomic_fetch_add_64_seq_cst(value, -1) - 1;
  105. }
  106. static inline uint64_t Decrement64(uint64_t* value)
  107. {
  108. return (uint64_t)Decrement64((int64_t*)value);
  109. }
  110. #endif
  111. static inline int32_t CompareExchange(int32_t* dest, int32_t exchange, int32_t comparand)
  112. {
  113. Baselib_atomic_compare_exchange_strong_32_seq_cst_seq_cst(dest, &comparand, exchange);
  114. return comparand;
  115. }
  116. static inline uint32_t CompareExchange(uint32_t* value, uint32_t newValue, uint32_t oldValue)
  117. {
  118. return (uint32_t)CompareExchange((int32_t*)value, newValue, oldValue);
  119. }
  120. static inline int64_t CompareExchange64(int64_t* dest, int64_t exchange, int64_t comparand)
  121. {
  122. Baselib_atomic_compare_exchange_strong_64_seq_cst_seq_cst(dest, &comparand, exchange);
  123. return comparand;
  124. }
  125. static inline uint64_t CompareExchange64(uint64_t* value, uint64_t newValue, uint64_t oldValue)
  126. {
  127. return (uint64_t)CompareExchange64((int64_t*)value, newValue, oldValue);
  128. }
  129. static inline bool Exchange(bool* dest, bool exchange)
  130. {
  131. return (bool)Baselib_atomic_exchange_8_seq_cst((int8_t*)dest, exchange);
  132. }
  133. static inline int32_t Exchange(int32_t* dest, int32_t exchange)
  134. {
  135. return Baselib_atomic_exchange_32_seq_cst(dest, exchange);
  136. }
  137. static inline uint32_t Exchange(uint32_t* value, uint32_t newValue)
  138. {
  139. return (uint32_t)Exchange((int32_t*)value, newValue);
  140. }
  141. #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
  142. static inline int64_t Exchange64(int64_t* dest, int64_t exchange)
  143. {
  144. return Baselib_atomic_exchange_64_seq_cst(dest, exchange);
  145. }
  146. static inline uint64_t Exchange64(uint64_t* value, uint64_t newValue)
  147. {
  148. return (uint64_t)Exchange64((int64_t*)value, newValue);
  149. }
  150. #endif
  151. static inline intptr_t ReadPtrVal(intptr_t* addr)
  152. {
  153. return Baselib_atomic_fetch_add_ptr_seq_cst(addr, 0);
  154. }
  155. };
  156. }
  157. }