cpu.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2010-2015 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_CPU_H_HEADER_GUARD
  6. #define BX_CPU_H_HEADER_GUARD
  7. #include "bx.h"
  8. #if BX_COMPILER_MSVC
  9. # if BX_PLATFORM_XBOX360
  10. # include <ppcintrinsics.h>
  11. # include <xtl.h>
  12. # else
  13. # include <math.h> // math.h is included because VS bitches:
  14. // warning C4985: 'ceil': attributes not present on previous declaration.
  15. // must be included before intrin.h.
  16. # include <intrin.h>
  17. # include <windows.h>
  18. # endif // !BX_PLATFORM_XBOX360
  19. extern "C" void _ReadBarrier();
  20. extern "C" void _WriteBarrier();
  21. extern "C" void _ReadWriteBarrier();
  22. # pragma intrinsic(_ReadBarrier)
  23. # pragma intrinsic(_WriteBarrier)
  24. # pragma intrinsic(_ReadWriteBarrier)
  25. # pragma intrinsic(_InterlockedExchangeAdd)
  26. # pragma intrinsic(_InterlockedCompareExchange)
  27. #endif // BX_COMPILER_MSVC
  28. namespace bx
  29. {
  30. ///
  31. inline void readBarrier()
  32. {
  33. #if BX_COMPILER_MSVC
  34. _ReadBarrier();
  35. #else
  36. asm volatile("":::"memory");
  37. #endif // BX_COMPILER
  38. }
  39. ///
  40. inline void writeBarrier()
  41. {
  42. #if BX_COMPILER_MSVC
  43. _WriteBarrier();
  44. #else
  45. asm volatile("":::"memory");
  46. #endif // BX_COMPILER
  47. }
  48. ///
  49. inline void readWriteBarrier()
  50. {
  51. #if BX_COMPILER_MSVC
  52. _ReadWriteBarrier();
  53. #else
  54. asm volatile("":::"memory");
  55. #endif // BX_COMPILER
  56. }
  57. ///
  58. inline void memoryBarrier()
  59. {
  60. #if BX_PLATFORM_XBOX360
  61. __lwsync();
  62. #elif BX_PLATFORM_WINRT
  63. MemoryBarrier();
  64. #elif BX_COMPILER_MSVC
  65. _mm_mfence();
  66. #else
  67. __sync_synchronize();
  68. // asm volatile("mfence":::"memory");
  69. #endif // BX_COMPILER
  70. }
  71. inline int32_t atomicFetchAndAdd(volatile int32_t* _ptr, int32_t _add)
  72. {
  73. #if BX_COMPILER_MSVC
  74. return _InterlockedExchangeAdd( (volatile long*)_ptr, _add);
  75. #else
  76. return __sync_fetch_and_add(_ptr, _add);
  77. #endif // BX_COMPILER_
  78. }
  79. inline int32_t atomicAddAndFetch(volatile int32_t* _ptr, int32_t _add)
  80. {
  81. #if BX_COMPILER_MSVC
  82. return atomicFetchAndAdd(_ptr, _add) + _add;
  83. #else
  84. return __sync_add_and_fetch(_ptr, _add);
  85. #endif // BX_COMPILER_
  86. }
  87. inline int32_t atomicFetchAndSub(volatile int32_t* _ptr, int32_t _sub)
  88. {
  89. #if BX_COMPILER_MSVC
  90. return atomicFetchAndAdd(_ptr, -_sub);
  91. #else
  92. return __sync_fetch_and_sub(_ptr, _sub);
  93. #endif // BX_COMPILER_
  94. }
  95. inline int32_t atomicSubAndFetch(volatile int32_t* _ptr, int32_t _sub)
  96. {
  97. #if BX_COMPILER_MSVC
  98. return atomicFetchAndAdd(_ptr, -_sub) - _sub;
  99. #else
  100. return __sync_sub_and_fetch(_ptr, _sub);
  101. #endif // BX_COMPILER_
  102. }
  103. /// Returns the resulting incremented value.
  104. inline int32_t atomicInc(volatile int32_t* _ptr)
  105. {
  106. return atomicAddAndFetch(_ptr, 1);
  107. }
  108. /// Returns the resulting decremented value.
  109. inline int32_t atomicDec(volatile int32_t* _ptr)
  110. {
  111. return atomicSubAndFetch(_ptr, 1);
  112. }
  113. ///
  114. inline int32_t atomicCompareAndSwap(volatile void* _ptr, int32_t _old, int32_t _new)
  115. {
  116. #if BX_COMPILER_MSVC
  117. return _InterlockedCompareExchange( (volatile LONG*)(_ptr), _new, _old);
  118. #else
  119. return __sync_val_compare_and_swap( (volatile int32_t*)_ptr, _old, _new);
  120. #endif // BX_COMPILER
  121. }
  122. ///
  123. inline void* atomicExchangePtr(void** _ptr, void* _new)
  124. {
  125. #if BX_COMPILER_MSVC
  126. return InterlockedExchangePointer(_ptr, _new);
  127. #else
  128. return __sync_lock_test_and_set(_ptr, _new);
  129. #endif // BX_COMPILER
  130. }
  131. ///
  132. inline int32_t atomicTestAndInc(volatile void* _ptr, int32_t _test)
  133. {
  134. int32_t oldVal;
  135. int32_t newVal = *(int32_t volatile*)_ptr;
  136. do
  137. {
  138. oldVal = newVal;
  139. newVal = atomicCompareAndSwap(_ptr, oldVal, newVal >= _test ? _test : newVal+1);
  140. } while (oldVal != newVal);
  141. return oldVal;
  142. }
  143. ///
  144. inline int32_t atomicTestAndDec(volatile void* _ptr, int32_t _test)
  145. {
  146. int32_t oldVal;
  147. int32_t newVal = *(int32_t volatile*)_ptr;
  148. do
  149. {
  150. oldVal = newVal;
  151. newVal = atomicCompareAndSwap(_ptr, oldVal, newVal <= _test ? _test : newVal-1);
  152. } while (oldVal != newVal);
  153. return oldVal;
  154. }
  155. } // namespace bx
  156. #endif // BX_CPU_H_HEADER_GUARD