1 // Copyright (c) 2011 Helge Bahmann
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)
7 // Verify that definition of the "LOCK_FREE" macros and the
8 // "is_lock_free" members is consistent and matches expectations.
9 // Also, if any operation is lock-free, then the platform
10 // implementation must provide overridden fence implementations.
12 #include <boost/atomic.hpp>
15 #include <boost/config.hpp>
16 #include <boost/core/lightweight_test.hpp>
18 static const char * lock_free_level[] = {
26 verify_lock_free(const char * type_name, int lock_free_macro_val, int lock_free_expect)
28 BOOST_TEST(lock_free_macro_val >= 0 && lock_free_macro_val <= 2);
29 BOOST_TEST(lock_free_macro_val == lock_free_expect);
31 boost::atomic<T> value;
33 if (lock_free_macro_val == 0)
34 BOOST_TEST(!value.is_lock_free());
35 if (lock_free_macro_val == 2)
36 BOOST_TEST(value.is_lock_free());
38 BOOST_TEST(boost::atomic<T>::is_always_lock_free == (lock_free_expect == 2));
40 std::cout << "atomic<" << type_name << "> is " << lock_free_level[lock_free_macro_val] << " lock free\n";
43 #if (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__i386__)
45 #define EXPECT_CHAR_LOCK_FREE 2
46 #define EXPECT_SHORT_LOCK_FREE 2
47 #define EXPECT_INT_LOCK_FREE 2
48 #define EXPECT_LONG_LOCK_FREE 2
49 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
50 #define EXPECT_LLONG_LOCK_FREE 2
52 #define EXPECT_LLONG_LOCK_FREE 0
54 #define EXPECT_INT128_LOCK_FREE 0
55 #define EXPECT_POINTER_LOCK_FREE 2
56 #define EXPECT_BOOL_LOCK_FREE 2
58 #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__x86_64__)
60 #define EXPECT_CHAR_LOCK_FREE 2
61 #define EXPECT_SHORT_LOCK_FREE 2
62 #define EXPECT_INT_LOCK_FREE 2
63 #define EXPECT_LONG_LOCK_FREE 2
64 #define EXPECT_LLONG_LOCK_FREE 2
65 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
66 #define EXPECT_INT128_LOCK_FREE 2
68 #define EXPECT_INT128_LOCK_FREE 0
70 #define EXPECT_POINTER_LOCK_FREE 2
71 #define EXPECT_BOOL_LOCK_FREE 2
73 #elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__))
75 #define EXPECT_CHAR_LOCK_FREE 2
76 #define EXPECT_CHAR16_T_LOCK_FREE 2
77 #define EXPECT_CHAR32_T_LOCK_FREE 2
78 #define EXPECT_WCHAR_T_LOCK_FREE 2
79 #define EXPECT_SHORT_LOCK_FREE 2
80 #define EXPECT_INT_LOCK_FREE 2
81 #define EXPECT_LONG_LOCK_FREE 2
82 #if defined(__powerpc64__)
83 #define EXPECT_LLONG_LOCK_FREE 2
85 #define EXPECT_LLONG_LOCK_FREE 0
87 #define EXPECT_INT128_LOCK_FREE 0
88 #define EXPECT_POINTER_LOCK_FREE 2
89 #define EXPECT_BOOL_LOCK_FREE 2
91 #elif defined(__GNUC__) && defined(__alpha__)
93 #define EXPECT_CHAR_LOCK_FREE 2
94 #define EXPECT_CHAR16_T_LOCK_FREE 2
95 #define EXPECT_CHAR32_T_LOCK_FREE 2
96 #define EXPECT_WCHAR_T_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 #define EXPECT_LLONG_LOCK_FREE 2
101 #define EXPECT_INT128_LOCK_FREE 0
102 #define EXPECT_POINTER_LOCK_FREE 2
103 #define EXPECT_BOOL_LOCK_FREE 2
105 #elif defined(__GNUC__) &&\
107 defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) ||\
108 defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) ||\
109 defined(__ARM_ARCH_6ZK__) ||\
110 defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\
111 defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\
112 defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)\
115 #define EXPECT_CHAR_LOCK_FREE 2
116 #define EXPECT_SHORT_LOCK_FREE 2
117 #define EXPECT_INT_LOCK_FREE 2
118 #define EXPECT_LONG_LOCK_FREE 2
119 #if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__)\
120 || ((defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)) && defined(__thumb__)) || defined(__ARM_ARCH_7M__))
121 #define EXPECT_LLONG_LOCK_FREE 2
123 #define EXPECT_LLONG_LOCK_FREE 0
125 #define EXPECT_INT128_LOCK_FREE 0
126 #define EXPECT_POINTER_LOCK_FREE 2
127 #define EXPECT_BOOL_LOCK_FREE 2
129 #elif defined(__linux__) && defined(__arm__)
131 #define EXPECT_CHAR_LOCK_FREE 2
132 #define EXPECT_SHORT_LOCK_FREE 2
133 #define EXPECT_INT_LOCK_FREE 2
134 #define EXPECT_LONG_LOCK_FREE 2
135 #define EXPECT_LLONG_LOCK_FREE 0
136 #define EXPECT_INT128_LOCK_FREE 0
137 #define EXPECT_POINTER_LOCK_FREE 2
138 #define EXPECT_BOOL_LOCK_FREE 2
140 #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__sparcv8plus) || defined(__sparc_v9__))
142 #define EXPECT_CHAR_LOCK_FREE 2
143 #define EXPECT_SHORT_LOCK_FREE 2
144 #define EXPECT_INT_LOCK_FREE 2
145 #define EXPECT_LONG_LOCK_FREE 2
146 #define EXPECT_LLONG_LOCK_FREE 2
147 #define EXPECT_INT128_LOCK_FREE 0
148 #define EXPECT_POINTER_LOCK_FREE 2
149 #define EXPECT_BOOL_LOCK_FREE 2
151 #elif defined(BOOST_USE_WINDOWS_H) || defined(_WIN32_CE) || defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
153 #define EXPECT_CHAR_LOCK_FREE 2
154 #define EXPECT_SHORT_LOCK_FREE 2
155 #define EXPECT_INT_LOCK_FREE 2
156 #define EXPECT_LONG_LOCK_FREE 2
157 #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)))
158 #define EXPECT_LLONG_LOCK_FREE 2
160 #define EXPECT_LLONG_LOCK_FREE 0
162 #define EXPECT_INT128_LOCK_FREE 0
163 #define EXPECT_POINTER_LOCK_FREE 2
164 #define EXPECT_BOOL_LOCK_FREE 2
168 #define EXPECT_CHAR_LOCK_FREE 0
169 #define EXPECT_SHORT_LOCK_FREE 0
170 #define EXPECT_INT_LOCK_FREE 0
171 #define EXPECT_LONG_LOCK_FREE 0
172 #define EXPECT_LLONG_LOCK_FREE 0
173 #define EXPECT_INT128_LOCK_FREE 0
174 #define EXPECT_POINTER_LOCK_FREE 0
175 #define EXPECT_BOOL_LOCK_FREE 0
179 int main(int, char *[])
181 verify_lock_free<char>("char", BOOST_ATOMIC_CHAR_LOCK_FREE, EXPECT_CHAR_LOCK_FREE);
182 verify_lock_free<short>("short", BOOST_ATOMIC_SHORT_LOCK_FREE, EXPECT_SHORT_LOCK_FREE);
183 verify_lock_free<int>("int", BOOST_ATOMIC_INT_LOCK_FREE, EXPECT_INT_LOCK_FREE);
184 verify_lock_free<long>("long", BOOST_ATOMIC_LONG_LOCK_FREE, EXPECT_LONG_LOCK_FREE);
185 #ifdef BOOST_HAS_LONG_LONG
186 verify_lock_free<long long>("long long", BOOST_ATOMIC_LLONG_LOCK_FREE, EXPECT_LLONG_LOCK_FREE);
188 #ifdef BOOST_HAS_INT128
189 verify_lock_free<boost::int128_type>("int128", BOOST_ATOMIC_INT128_LOCK_FREE, EXPECT_INT128_LOCK_FREE);
191 verify_lock_free<void *>("void *", BOOST_ATOMIC_POINTER_LOCK_FREE, EXPECT_SHORT_LOCK_FREE);
192 verify_lock_free<bool>("bool", BOOST_ATOMIC_BOOL_LOCK_FREE, EXPECT_BOOL_LOCK_FREE);
194 #ifndef BOOST_ATOMIC_NO_FLOATING_POINT
196 verify_lock_free<float>("float", BOOST_ATOMIC_FLOAT_LOCK_FREE,
197 sizeof(float) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(float) == 2 ? EXPECT_SHORT_LOCK_FREE :
198 (sizeof(float) <= 4 ? EXPECT_INT_LOCK_FREE : (sizeof(float) <= 8 ? EXPECT_LLONG_LOCK_FREE : (sizeof(float) <= 16 ? EXPECT_INT128_LOCK_FREE : 0)))));
200 verify_lock_free<double>("double", BOOST_ATOMIC_DOUBLE_LOCK_FREE,
201 sizeof(double) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(double) == 2 ? EXPECT_SHORT_LOCK_FREE :
202 (sizeof(double) <= 4 ? EXPECT_INT_LOCK_FREE : (sizeof(double) <= 8 ? EXPECT_LLONG_LOCK_FREE : (sizeof(double) <= 16 ? EXPECT_INT128_LOCK_FREE : 0)))));
204 verify_lock_free<long double>("long double", BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE,
205 sizeof(long double) == 1 ? EXPECT_CHAR_LOCK_FREE : (sizeof(long double) == 2 ? EXPECT_SHORT_LOCK_FREE :
206 (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)))));
208 #if defined(BOOST_HAS_INT128) && defined(BOOST_HAS_FLOAT128)
209 verify_lock_free<boost::float128_type>("float128", BOOST_ATOMIC_INT128_LOCK_FREE, EXPECT_INT128_LOCK_FREE);
212 #endif // BOOST_ATOMIC_NO_FLOATING_POINT
215 BOOST_ATOMIC_CHAR_LOCK_FREE > 0 ||
216 BOOST_ATOMIC_SHORT_LOCK_FREE > 0 ||
217 BOOST_ATOMIC_INT_LOCK_FREE > 0 ||
218 BOOST_ATOMIC_LONG_LOCK_FREE > 0 ||
219 BOOST_ATOMIC_LLONG_LOCK_FREE > 0 ||
220 BOOST_ATOMIC_BOOL_LOCK_FREE > 0;
222 BOOST_TEST(!any_lock_free || BOOST_ATOMIC_THREAD_FENCE > 0);
224 return boost::report_errors();