cpu.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright 2010-2013 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(_InterlockedIncrement)
  26. # pragma intrinsic(_InterlockedDecrement)
  27. # pragma intrinsic(_InterlockedCompareExchange)
  28. #endif // BX_COMPILER_MSVC
  29. namespace bx
  30. {
  31. ///
  32. inline void readBarrier()
  33. {
  34. #if BX_COMPILER_MSVC
  35. _ReadBarrier();
  36. #else
  37. asm volatile("":::"memory");
  38. #endif // BX_COMPILER
  39. }
  40. ///
  41. inline void writeBarrier()
  42. {
  43. #if BX_COMPILER_MSVC
  44. _WriteBarrier();
  45. #else
  46. asm volatile("":::"memory");
  47. #endif // BX_COMPILER
  48. }
  49. ///
  50. inline void readWriteBarrier()
  51. {
  52. #if BX_COMPILER_MSVC
  53. _ReadWriteBarrier();
  54. #else
  55. asm volatile("":::"memory");
  56. #endif // BX_COMPILER
  57. }
  58. ///
  59. inline void memoryBarrier()
  60. {
  61. #if BX_PLATFORM_XBOX360
  62. __lwsync();
  63. #elif BX_PLATFORM_WINRT
  64. MemoryBarrier();
  65. #elif BX_COMPILER_MSVC
  66. _mm_mfence();
  67. #else
  68. __sync_synchronize();
  69. // asm volatile("mfence":::"memory");
  70. #endif // BX_COMPILER
  71. }
  72. /// Returns the resulting incremented value.
  73. inline int32_t atomicInc(volatile void* _ptr)
  74. {
  75. #if BX_COMPILER_MSVC
  76. return _InterlockedIncrement( (volatile LONG*)(_ptr) );
  77. #else
  78. return __sync_add_and_fetch( (volatile int32_t*)_ptr, 1);
  79. #endif // BX_COMPILER
  80. }
  81. /// Returns the resulting decremented value.
  82. inline int32_t atomicDec(volatile void* _ptr)
  83. {
  84. #if BX_COMPILER_MSVC
  85. return _InterlockedDecrement( (volatile LONG*)(_ptr) );
  86. #else
  87. return __sync_sub_and_fetch( (volatile int32_t*)_ptr, 1);
  88. #endif // BX_COMPILER
  89. }
  90. ///
  91. inline int32_t atomicCompareAndSwap(volatile void* _ptr, int32_t _old, int32_t _new)
  92. {
  93. #if BX_COMPILER_MSVC
  94. return _InterlockedCompareExchange( (volatile LONG*)(_ptr), _new, _old);
  95. #else
  96. return __sync_val_compare_and_swap( (volatile int32_t*)_ptr, _old, _new);
  97. #endif // BX_COMPILER
  98. }
  99. ///
  100. inline void* atomicExchangePtr(void** _ptr, void* _new)
  101. {
  102. #if BX_COMPILER_MSVC
  103. return InterlockedExchangePointer(_ptr, _new); /* VS2012 no intrinsics */
  104. #else
  105. return __sync_lock_test_and_set(_ptr, _new);
  106. #endif // BX_COMPILER
  107. }
  108. ///
  109. inline int32_t atomicTestAndInc(volatile void* _ptr, int32_t _test)
  110. {
  111. int32_t oldVal;
  112. int32_t newVal = *(int32_t volatile*)_ptr;
  113. do
  114. {
  115. oldVal = newVal;
  116. newVal = atomicCompareAndSwap(_ptr, oldVal, newVal >= _test ? _test : newVal+1);
  117. } while (oldVal != newVal);
  118. return oldVal;
  119. }
  120. ///
  121. inline int32_t atomicTestAndDec(volatile void* _ptr, int32_t _test)
  122. {
  123. int32_t oldVal;
  124. int32_t newVal = *(int32_t volatile*)_ptr;
  125. do
  126. {
  127. oldVal = newVal;
  128. newVal = atomicCompareAndSwap(_ptr, oldVal, newVal <= _test ? _test : newVal-1);
  129. } while (oldVal != newVal);
  130. return oldVal;
  131. }
  132. } // namespace bx
  133. #endif // BX_CPU_H_HEADER_GUARD