lockfree.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright (c) 2011 Helge Bahmann
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // Verify that definition of the "LOCK_FREE" macros and the
  7. // "is_lock_free" members is consistent and matches expectations.
  8. // Also, if any operation is lock-free, then the platform
  9. // implementation must provide overridden fence implementations.
  10. #include <boost/atomic.hpp>
  11. #include <iostream>
  12. #include <boost/config.hpp>
  13. #include <boost/core/lightweight_test.hpp>
  14. static const char * lock_free_level[] = {
  15. "never",
  16. "sometimes",
  17. "always"
  18. };
  19. template<typename T>
  20. void
  21. verify_lock_free(const char * type_name, int lock_free_macro_val, int lock_free_expect)
  22. {
  23. BOOST_TEST(lock_free_macro_val >= 0 && lock_free_macro_val <= 2);
  24. BOOST_TEST(lock_free_macro_val == lock_free_expect);
  25. boost::atomic<T> value;
  26. if (lock_free_macro_val == 0)
  27. BOOST_TEST(!value.is_lock_free());
  28. if (lock_free_macro_val == 2)
  29. BOOST_TEST(value.is_lock_free());
  30. BOOST_TEST(boost::atomic<T>::is_always_lock_free == (lock_free_expect == 2));
  31. std::cout << "atomic<" << type_name << "> is " << lock_free_level[lock_free_macro_val] << " lock free\n";
  32. }
  33. #if (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__i386__)
  34. #define EXPECT_CHAR_LOCK_FREE 2
  35. #define EXPECT_SHORT_LOCK_FREE 2
  36. #define EXPECT_INT_LOCK_FREE 2
  37. #define EXPECT_LONG_LOCK_FREE 2
  38. #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
  39. #define EXPECT_LLONG_LOCK_FREE 2
  40. #else
  41. #define EXPECT_LLONG_LOCK_FREE 0
  42. #endif
  43. #define EXPECT_INT128_LOCK_FREE 0
  44. #define EXPECT_POINTER_LOCK_FREE 2
  45. #define EXPECT_BOOL_LOCK_FREE 2
  46. #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__x86_64__)
  47. #define EXPECT_CHAR_LOCK_FREE 2
  48. #define EXPECT_SHORT_LOCK_FREE 2
  49. #define EXPECT_INT_LOCK_FREE 2
  50. #define EXPECT_LONG_LOCK_FREE 2
  51. #define EXPECT_LLONG_LOCK_FREE 2
  52. #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
  53. #define EXPECT_INT128_LOCK_FREE 2
  54. #else
  55. #define EXPECT_INT128_LOCK_FREE 0
  56. #endif
  57. #define EXPECT_POINTER_LOCK_FREE 2
  58. #define EXPECT_BOOL_LOCK_FREE 2
  59. #elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__))
  60. #define EXPECT_CHAR_LOCK_FREE 2
  61. #define EXPECT_CHAR16_T_LOCK_FREE 2
  62. #define EXPECT_CHAR32_T_LOCK_FREE 2
  63. #define EXPECT_WCHAR_T_LOCK_FREE 2
  64. #define EXPECT_SHORT_LOCK_FREE 2
  65. #define EXPECT_INT_LOCK_FREE 2
  66. #define EXPECT_LONG_LOCK_FREE 2
  67. #if defined(__powerpc64__)
  68. #define EXPECT_LLONG_LOCK_FREE 2
  69. #else
  70. #define EXPECT_LLONG_LOCK_FREE 0
  71. #endif
  72. #define EXPECT_INT128_LOCK_FREE 0
  73. #define EXPECT_POINTER_LOCK_FREE 2
  74. #define EXPECT_BOOL_LOCK_FREE 2
  75. #elif defined(__GNUC__) && defined(__alpha__)
  76. #define EXPECT_CHAR_LOCK_FREE 2
  77. #define EXPECT_CHAR16_T_LOCK_FREE 2
  78. #define EXPECT_CHAR32_T_LOCK_FREE 2
  79. #define EXPECT_WCHAR_T_LOCK_FREE 2
  80. #define EXPECT_SHORT_LOCK_FREE 2
  81. #define EXPECT_INT_LOCK_FREE 2
  82. #define EXPECT_LONG_LOCK_FREE 2
  83. #define EXPECT_LLONG_LOCK_FREE 2
  84. #define EXPECT_INT128_LOCK_FREE 0
  85. #define EXPECT_POINTER_LOCK_FREE 2
  86. #define EXPECT_BOOL_LOCK_FREE 2
  87. #elif defined(__GNUC__) &&\
  88. (\
  89. defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) ||\
  90. defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) ||\
  91. defined(__ARM_ARCH_6ZK__) ||\
  92. defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\
  93. defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\
  94. defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)\
  95. )
  96. #define EXPECT_CHAR_LOCK_FREE 2
  97. #define EXPECT_SHORT_LOCK_FREE 2
  98. #define EXPECT_INT_LOCK_FREE 2
  99. #define EXPECT_LONG_LOCK_FREE 2
  100. #if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__)\
  101. || ((defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)) && defined(__thumb__)) || defined(__ARM_ARCH_7M__))
  102. #define EXPECT_LLONG_LOCK_FREE 2
  103. #else
  104. #define EXPECT_LLONG_LOCK_FREE 0
  105. #endif
  106. #define EXPECT_INT128_LOCK_FREE 0
  107. #define EXPECT_POINTER_LOCK_FREE 2
  108. #define EXPECT_BOOL_LOCK_FREE 2
  109. #elif defined(__linux__) && defined(__arm__)
  110. #define EXPECT_CHAR_LOCK_FREE 2
  111. #define EXPECT_SHORT_LOCK_FREE 2
  112. #define EXPECT_INT_LOCK_FREE 2
  113. #define EXPECT_LONG_LOCK_FREE 2
  114. #define EXPECT_LLONG_LOCK_FREE 0
  115. #define EXPECT_INT128_LOCK_FREE 0
  116. #define EXPECT_POINTER_LOCK_FREE 2
  117. #define EXPECT_BOOL_LOCK_FREE 2
  118. #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__sparcv8plus) || defined(__sparc_v9__))
  119. #define EXPECT_CHAR_LOCK_FREE 2
  120. #define EXPECT_SHORT_LOCK_FREE 2
  121. #define EXPECT_INT_LOCK_FREE 2
  122. #define EXPECT_LONG_LOCK_FREE 2
  123. #define EXPECT_LLONG_LOCK_FREE 2
  124. #define EXPECT_INT128_LOCK_FREE 0
  125. #define EXPECT_POINTER_LOCK_FREE 2
  126. #define EXPECT_BOOL_LOCK_FREE 2
  127. #elif defined(BOOST_USE_WINDOWS_H) || defined(_WIN32_CE) || defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
  128. #define EXPECT_CHAR_LOCK_FREE 2
  129. #define EXPECT_SHORT_LOCK_FREE 2
  130. #define EXPECT_INT_LOCK_FREE 2
  131. #define EXPECT_LONG_LOCK_FREE 2
  132. #if defined(_WIN64) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(_M_AMD64) || defined(_M_IA64) || (_MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64)))
  133. #define EXPECT_LLONG_LOCK_FREE 2
  134. #else
  135. #define EXPECT_LLONG_LOCK_FREE 0
  136. #endif
  137. #define EXPECT_INT128_LOCK_FREE 0
  138. #define EXPECT_POINTER_LOCK_FREE 2
  139. #define EXPECT_BOOL_LOCK_FREE 2
  140. #else
  141. #define EXPECT_CHAR_LOCK_FREE 0
  142. #define EXPECT_SHORT_LOCK_FREE 0
  143. #define EXPECT_INT_LOCK_FREE 0
  144. #define EXPECT_LONG_LOCK_FREE 0
  145. #define EXPECT_LLONG_LOCK_FREE 0
  146. #define EXPECT_INT128_LOCK_FREE 0
  147. #define EXPECT_POINTER_LOCK_FREE 0
  148. #define EXPECT_BOOL_LOCK_FREE 0
  149. #endif
  150. int main(int, char *[])
  151. {
  152. verify_lock_free<char>("char", BOOST_ATOMIC_CHAR_LOCK_FREE, EXPECT_CHAR_LOCK_FREE);
  153. verify_lock_free<short>("short", BOOST_ATOMIC_SHORT_LOCK_FREE, EXPECT_SHORT_LOCK_FREE);
  154. verify_lock_free<int>("int", BOOST_ATOMIC_INT_LOCK_FREE, EXPECT_INT_LOCK_FREE);
  155. verify_lock_free<long>("long", BOOST_ATOMIC_LONG_LOCK_FREE, EXPECT_LONG_LOCK_FREE);
  156. #ifdef BOOST_HAS_LONG_LONG
  157. verify_lock_free<long long>("long long", BOOST_ATOMIC_LLONG_LOCK_FREE, EXPECT_LLONG_LOCK_FREE);
  158. #endif
  159. #ifdef BOOST_HAS_INT128
  160. verify_lock_free<boost::int128_type>("int128", BOOST_ATOMIC_INT128_LOCK_FREE, EXPECT_INT128_LOCK_FREE);
  161. #endif
  162. verify_lock_free<void *>("void *", BOOST_ATOMIC_POINTER_LOCK_FREE, EXPECT_SHORT_LOCK_FREE);
  163. verify_lock_free<bool>("bool", BOOST_ATOMIC_BOOL_LOCK_FREE, EXPECT_BOOL_LOCK_FREE);
  164. #ifndef BOOST_ATOMIC_NO_FLOATING_POINT
  165. verify_lock_free<float>("float", BOOST_ATOMIC_FLOAT_LOCK_FREE,
  166. sizeof(float) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(float) == 2 ? EXPECT_SHORT_LOCK_FREE :
  167. (sizeof(float) <= 4 ? EXPECT_INT_LOCK_FREE : (sizeof(float) <= 8 ? EXPECT_LLONG_LOCK_FREE : (sizeof(float) <= 16 ? EXPECT_INT128_LOCK_FREE : 0)))));
  168. verify_lock_free<double>("double", BOOST_ATOMIC_DOUBLE_LOCK_FREE,
  169. sizeof(double) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(double) == 2 ? EXPECT_SHORT_LOCK_FREE :
  170. (sizeof(double) <= 4 ? EXPECT_INT_LOCK_FREE : (sizeof(double) <= 8 ? EXPECT_LLONG_LOCK_FREE : (sizeof(double) <= 16 ? EXPECT_INT128_LOCK_FREE : 0)))));
  171. verify_lock_free<long double>("long double", BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE,
  172. sizeof(long double) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(long double) == 2 ? EXPECT_SHORT_LOCK_FREE :
  173. (sizeof(long double) <= 4 ? EXPECT_INT_LOCK_FREE : (sizeof(long double) <= 8 ? EXPECT_LLONG_LOCK_FREE : (sizeof(long double) <= 16 ? EXPECT_INT128_LOCK_FREE : 0)))));
  174. #if defined(BOOST_HAS_INT128) && defined(BOOST_HAS_FLOAT128)
  175. verify_lock_free<boost::float128_type>("float128", BOOST_ATOMIC_INT128_LOCK_FREE, EXPECT_INT128_LOCK_FREE);
  176. #endif
  177. #endif // BOOST_ATOMIC_NO_FLOATING_POINT
  178. bool any_lock_free =
  179. BOOST_ATOMIC_CHAR_LOCK_FREE > 0 ||
  180. BOOST_ATOMIC_SHORT_LOCK_FREE > 0 ||
  181. BOOST_ATOMIC_INT_LOCK_FREE > 0 ||
  182. BOOST_ATOMIC_LONG_LOCK_FREE > 0 ||
  183. BOOST_ATOMIC_LLONG_LOCK_FREE > 0 ||
  184. BOOST_ATOMIC_BOOL_LOCK_FREE > 0;
  185. BOOST_TEST(!any_lock_free || BOOST_ATOMIC_THREAD_FENCE > 0);
  186. return boost::report_errors();
  187. }