atomic_support.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //===----------------------------------------------------------------------===////
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is dual licensed under the MIT and the University of Illinois Open
  6. // Source Licenses. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===////
  9. #ifndef ATOMIC_SUPPORT_H
  10. #define ATOMIC_SUPPORT_H
  11. #include "__config"
  12. #include "memory" // for __libcpp_relaxed_load
  13. #if defined(__clang__) && __has_builtin(__atomic_load_n) \
  14. && __has_builtin(__atomic_store_n) \
  15. && __has_builtin(__atomic_add_fetch) \
  16. && __has_builtin(__atomic_compare_exchange_n) \
  17. && defined(__ATOMIC_RELAXED) \
  18. && defined(__ATOMIC_CONSUME) \
  19. && defined(__ATOMIC_ACQUIRE) \
  20. && defined(__ATOMIC_RELEASE) \
  21. && defined(__ATOMIC_ACQ_REL) \
  22. && defined(__ATOMIC_SEQ_CST)
  23. # define _LIBCPP_HAS_ATOMIC_BUILTINS
  24. #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
  25. # define _LIBCPP_HAS_ATOMIC_BUILTINS
  26. #endif
  27. #if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
  28. # if defined(_MSC_VER) && !defined(__clang__)
  29. _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
  30. # else
  31. # warning Building libc++ without __atomic builtins is unsupported
  32. # endif
  33. #endif
  34. _LIBCPP_BEGIN_NAMESPACE_STD
  35. namespace {
  36. #if defined(_LIBCPP_HAS_ATOMIC_BUILTINS)
  37. enum __libcpp_atomic_order {
  38. _AO_Relaxed = __ATOMIC_RELAXED,
  39. _AO_Consume = __ATOMIC_CONSUME,
  40. _AO_Acquire = __ATOMIC_ACQUIRE,
  41. _AO_Release = __ATOMIC_RELEASE,
  42. _AO_Acq_Rel = __ATOMIC_ACQ_REL,
  43. _AO_Seq = __ATOMIC_SEQ_CST
  44. };
  45. template <class _ValueType, class _FromType>
  46. inline _LIBCPP_INLINE_VISIBILITY
  47. void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
  48. int __order = _AO_Seq)
  49. {
  50. __atomic_store_n(__dest, __val, __order);
  51. }
  52. template <class _ValueType, class _FromType>
  53. inline _LIBCPP_INLINE_VISIBILITY
  54. void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
  55. {
  56. __atomic_store_n(__dest, __val, _AO_Relaxed);
  57. }
  58. template <class _ValueType>
  59. inline _LIBCPP_INLINE_VISIBILITY
  60. _ValueType __libcpp_atomic_load(_ValueType const* __val,
  61. int __order = _AO_Seq)
  62. {
  63. return __atomic_load_n(__val, __order);
  64. }
  65. template <class _ValueType, class _AddType>
  66. inline _LIBCPP_INLINE_VISIBILITY
  67. _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
  68. int __order = _AO_Seq)
  69. {
  70. return __atomic_add_fetch(__val, __a, __order);
  71. }
  72. template <class _ValueType>
  73. inline _LIBCPP_INLINE_VISIBILITY
  74. bool __libcpp_atomic_compare_exchange(_ValueType* __val,
  75. _ValueType* __expected, _ValueType __after,
  76. int __success_order = _AO_Seq,
  77. int __fail_order = _AO_Seq)
  78. {
  79. return __atomic_compare_exchange_n(__val, __expected, __after, true,
  80. __success_order, __fail_order);
  81. }
  82. #else // !(defined(_LIBCPP_HAS_ATOMIC_BUILTINS)
  83. enum __libcpp_atomic_order {
  84. _AO_Relaxed,
  85. _AO_Consume,
  86. _AO_Acquire,
  87. _AO_Release,
  88. _AO_Acq_Rel,
  89. _AO_Seq
  90. };
  91. template <class _ValueType, class _FromType>
  92. inline _LIBCPP_INLINE_VISIBILITY
  93. void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
  94. int = 0)
  95. {
  96. *__dest = __val;
  97. }
  98. template <class _ValueType, class _FromType>
  99. inline _LIBCPP_INLINE_VISIBILITY
  100. void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
  101. {
  102. *__dest = __val;
  103. }
  104. template <class _ValueType>
  105. inline _LIBCPP_INLINE_VISIBILITY
  106. _ValueType __libcpp_atomic_load(_ValueType const* __val,
  107. int = 0)
  108. {
  109. return *__val;
  110. }
  111. template <class _ValueType, class _AddType>
  112. inline _LIBCPP_INLINE_VISIBILITY
  113. _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
  114. int = 0)
  115. {
  116. return *__val += __a;
  117. }
  118. template <class _ValueType>
  119. inline _LIBCPP_INLINE_VISIBILITY
  120. bool __libcpp_atomic_compare_exchange(_ValueType* __val,
  121. _ValueType* __expected, _ValueType __after,
  122. int = 0, int = 0)
  123. {
  124. if (*__val == *__expected) {
  125. *__val = __after;
  126. return true;
  127. }
  128. *__expected = *__val;
  129. return false;
  130. }
  131. #endif // _LIBCPP_HAS_ATOMIC_BUILTINS
  132. } // end namespace
  133. _LIBCPP_END_NAMESPACE_STD
  134. #endif // ATOMIC_SUPPORT_H