b1ef72b8e1b1041829b34a58d804434e22fa12f7
[platform/upstream/boost.git] / libs / atomic / test / lockfree.cpp
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
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.
11
12 #include <boost/atomic.hpp>
13
14 #include <iostream>
15 #include <boost/config.hpp>
16 #include <boost/core/lightweight_test.hpp>
17
18 static const char * lock_free_level[] = {
19     "never",
20     "sometimes",
21     "always"
22 };
23
24 template<typename T>
25 void
26 verify_lock_free(const char * type_name, int lock_free_macro_val, int lock_free_expect)
27 {
28     BOOST_TEST(lock_free_macro_val >= 0 && lock_free_macro_val <= 2);
29     BOOST_TEST(lock_free_macro_val == lock_free_expect);
30
31     boost::atomic<T> value;
32
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());
37
38     BOOST_TEST(boost::atomic<T>::is_always_lock_free == (lock_free_expect == 2));
39
40     std::cout << "atomic<" << type_name << "> is " << lock_free_level[lock_free_macro_val] << " lock free\n";
41 }
42
43 #if (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__i386__)
44
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
51 #else
52 #define EXPECT_LLONG_LOCK_FREE 0
53 #endif
54 #define EXPECT_INT128_LOCK_FREE 0
55 #define EXPECT_POINTER_LOCK_FREE 2
56 #define EXPECT_BOOL_LOCK_FREE 2
57
58 #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__x86_64__)
59
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
67 #else
68 #define EXPECT_INT128_LOCK_FREE 0
69 #endif
70 #define EXPECT_POINTER_LOCK_FREE 2
71 #define EXPECT_BOOL_LOCK_FREE 2
72
73 #elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__))
74
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
84 #else
85 #define EXPECT_LLONG_LOCK_FREE 0
86 #endif
87 #define EXPECT_INT128_LOCK_FREE 0
88 #define EXPECT_POINTER_LOCK_FREE 2
89 #define EXPECT_BOOL_LOCK_FREE 2
90
91 #elif defined(__GNUC__) && defined(__alpha__)
92
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
104
105 #elif defined(__GNUC__) &&\
106     (\
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__)\
113     )
114
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
122 #else
123 #define EXPECT_LLONG_LOCK_FREE 0
124 #endif
125 #define EXPECT_INT128_LOCK_FREE 0
126 #define EXPECT_POINTER_LOCK_FREE 2
127 #define EXPECT_BOOL_LOCK_FREE 2
128
129 #elif defined(__linux__) && defined(__arm__)
130
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
139
140 #elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__sparcv8plus) || defined(__sparc_v9__))
141
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
150
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__)
152
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
159 #else
160 #define EXPECT_LLONG_LOCK_FREE 0
161 #endif
162 #define EXPECT_INT128_LOCK_FREE 0
163 #define EXPECT_POINTER_LOCK_FREE 2
164 #define EXPECT_BOOL_LOCK_FREE 2
165
166 #else
167
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
176
177 #endif
178
179 int main(int, char *[])
180 {
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);
187 #endif
188 #ifdef BOOST_HAS_INT128
189     verify_lock_free<boost::int128_type>("int128", BOOST_ATOMIC_INT128_LOCK_FREE, EXPECT_INT128_LOCK_FREE);
190 #endif
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);
193
194 #ifndef BOOST_ATOMIC_NO_FLOATING_POINT
195
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)))));
199
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)))));
203
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)))));
207
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);
210 #endif
211
212 #endif // BOOST_ATOMIC_NO_FLOATING_POINT
213
214     bool any_lock_free =
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;
221
222     BOOST_TEST(!any_lock_free || BOOST_ATOMIC_THREAD_FENCE > 0);
223
224     return boost::report_errors();
225 }