hdr_atomic.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /**
  2. * hdr_atomic.h
  3. * Written by Philip Orwig and released to the public domain,
  4. * as explained at http://creativecommons.org/publicdomain/zero/1.0/
  5. */
  6. #ifndef HDR_ATOMIC_H__
  7. #define HDR_ATOMIC_H__
  8. #if defined(_MSC_VER)
  9. #include <stdint.h>
  10. #include <intrin.h>
  11. #include <stdbool.h>
  12. static void __inline * hdr_atomic_load_pointer(void** pointer)
  13. {
  14. _ReadBarrier();
  15. return *pointer;
  16. }
  17. static void hdr_atomic_store_pointer(void** pointer, void* value)
  18. {
  19. _WriteBarrier();
  20. *pointer = value;
  21. }
  22. static int64_t __inline hdr_atomic_load_64(int64_t* field)
  23. {
  24. _ReadBarrier();
  25. return *field;
  26. }
  27. static void __inline hdr_atomic_store_64(int64_t* field, int64_t value)
  28. {
  29. _WriteBarrier();
  30. *field = value;
  31. }
  32. static int64_t __inline hdr_atomic_exchange_64(volatile int64_t* field, int64_t value)
  33. {
  34. #if defined(_WIN64)
  35. return _InterlockedExchange64(field, value);
  36. #else
  37. int64_t comparand;
  38. int64_t initial_value = *field;
  39. do
  40. {
  41. comparand = initial_value;
  42. initial_value = _InterlockedCompareExchange64(field, value, comparand);
  43. }
  44. while (comparand != initial_value);
  45. return initial_value;
  46. #endif
  47. }
  48. static int64_t __inline hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
  49. {
  50. #if defined(_WIN64)
  51. return _InterlockedExchangeAdd64(field, value) + value;
  52. #else
  53. int64_t comparand;
  54. int64_t initial_value = *field;
  55. do
  56. {
  57. comparand = initial_value;
  58. initial_value = _InterlockedCompareExchange64(field, comparand + value, comparand);
  59. }
  60. while (comparand != initial_value);
  61. return initial_value + value;
  62. #endif
  63. }
  64. static bool __inline hdr_atomic_compare_exchange_64(volatile int64_t* field, int64_t* expected, int64_t desired)
  65. {
  66. return *expected == _InterlockedCompareExchange64(field, desired, *expected);
  67. }
  68. #elif defined(__ATOMIC_SEQ_CST)
  69. #define hdr_atomic_load_pointer(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
  70. #define hdr_atomic_store_pointer(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
  71. #define hdr_atomic_load_64(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
  72. #define hdr_atomic_store_64(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
  73. #define hdr_atomic_exchange_64(f,i) __atomic_exchange_n(f,i, __ATOMIC_SEQ_CST)
  74. #define hdr_atomic_add_fetch_64(field, value) __atomic_add_fetch(field, value, __ATOMIC_SEQ_CST)
  75. #define hdr_atomic_compare_exchange_64(field, expected, desired) __atomic_compare_exchange_n(field, expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
  76. #elif defined(__x86_64__)
  77. #include <stdint.h>
  78. #include <stdbool.h>
  79. static inline void* hdr_atomic_load_pointer(void** pointer)
  80. {
  81. void* p = *pointer;
  82. asm volatile ("" ::: "memory");
  83. return p;
  84. }
  85. static inline void hdr_atomic_store_pointer(void** pointer, void* value)
  86. {
  87. asm volatile ("lock; xchgq %0, %1" : "+q" (value), "+m" (*pointer));
  88. }
  89. static inline int64_t hdr_atomic_load_64(int64_t* field)
  90. {
  91. int64_t i = *field;
  92. asm volatile ("" ::: "memory");
  93. return i;
  94. }
  95. static inline void hdr_atomic_store_64(int64_t* field, int64_t value)
  96. {
  97. asm volatile ("lock; xchgq %0, %1" : "+q" (value), "+m" (*field));
  98. }
  99. static inline int64_t hdr_atomic_exchange_64(volatile int64_t* field, int64_t value)
  100. {
  101. int64_t result = 0;
  102. asm volatile ("lock; xchgq %1, %2" : "=r" (result), "+q" (value), "+m" (*field));
  103. return result;
  104. }
  105. static inline int64_t hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
  106. {
  107. return __sync_add_and_fetch(field, value);
  108. }
  109. static inline bool hdr_atomic_compare_exchange_64(volatile int64_t* field, int64_t* expected, int64_t desired)
  110. {
  111. int64_t original;
  112. asm volatile( "lock; cmpxchgq %2, %1" : "=a"(original), "+m"(*field) : "q"(desired), "0"(*expected));
  113. return original == *expected;
  114. }
  115. #else
  116. #error "Unable to determine atomic operations for your platform"
  117. #endif
  118. #endif /* HDR_ATOMIC_H__ */