Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / atomic / detail / ops_gcc_atomic.hpp @ 2486

History | View | Annotate | Download (15.5 kB)

1
/*
2
 * Distributed under the Boost Software License, Version 1.0.
3
 * (See accompanying file LICENSE_1_0.txt or copy at
4
 * http://www.boost.org/LICENSE_1_0.txt)
5
 *
6
 * Copyright (c) 2014 Andrey Semashev
7
 */
8
/*!
9
 * \file   atomic/detail/ops_gcc_atomic.hpp
10
 *
11
 * This header contains implementation of the \c operations template.
12
 */
13

    
14
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_
15
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_
16

    
17
#include <boost/memory_order.hpp>
18
#include <boost/atomic/detail/config.hpp>
19
#include <boost/atomic/detail/storage_type.hpp>
20
#include <boost/atomic/detail/operations_fwd.hpp>
21
#include <boost/atomic/capabilities.hpp>
22
#if defined(__clang__) && (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B))
23
#include <boost/atomic/detail/ops_gcc_x86_dcas.hpp>
24
#include <boost/atomic/detail/ops_cas_based.hpp>
25
#endif
26

    
27
#if __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE ||\
28
    __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE || __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE ||\
29
    __GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE || __GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE ||\
30
    __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE
31
// There are platforms where we need to use larger storage types
32
#include <boost/atomic/detail/int_sizes.hpp>
33
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
34
#endif
35

    
36
#ifdef BOOST_HAS_PRAGMA_ONCE
37
#pragma once
38
#endif
39

    
40
#if defined(__INTEL_COMPILER)
41
// This is used to suppress warning #32013 described below for Intel Compiler.
42
// In debug builds the compiler does not inline any functions, so basically
43
// every atomic function call results in this warning. I don't know any other
44
// way to selectively disable just this one warning.
45
#pragma system_header
46
#endif
47

    
48
namespace boost {
49
namespace atomics {
50
namespace detail {
51

    
52
/*!
53
 * The function converts \c boost::memory_order values to the compiler-specific constants.
54
 *
55
 * NOTE: The intention is that the function is optimized away by the compiler, and the
56
 *       compiler-specific constants are passed to the intrinsics. I know constexpr doesn't
57
 *       work in this case because the standard atomics interface require memory ordering
58
 *       constants to be passed as function arguments, at which point they stop being constexpr.
59
 *       However it is crucial that the compiler sees constants and not runtime values,
60
 *       because otherwise it just ignores the ordering value and always uses seq_cst.
61
 *       This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and
62
 *       gcc 4.8.2. Intel Compiler issues a warning in this case:
63
 *
64
 *       warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order.
65
 *
66
 *       while gcc acts silently.
67
 *
68
 *       To mitigate the problem ALL functions, including the atomic<> members must be
69
 *       declared with BOOST_FORCEINLINE. In this case the compilers are able to see that
70
 *       all functions are called with constant orderings and call intrinstcts properly.
71
 *
72
 *       Unfortunately, this still doesn't work in debug mode as the compiler doesn't
73
 *       inline functions even when marked with BOOST_FORCEINLINE. In this case all atomic
74
 *       operaions will be executed with seq_cst semantics.
75
 */
76
BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT
77
{
78
    return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME :
79
        (order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE :
80
        (order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST)))));
81
}
82

    
83
template< typename T >
84
struct gcc_atomic_operations
85
{
86
    typedef T storage_type;
87

    
88
    static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
89
    {
90
        __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
91
    }
92

    
93
    static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
94
    {
95
        return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order));
96
    }
97

    
98
    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
99
    {
100
        return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
101
    }
102

    
103
    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
104
    {
105
        return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
106
    }
107

    
108
    static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
109
    {
110
        return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
111
    }
112

    
113
    static BOOST_FORCEINLINE bool compare_exchange_strong(
114
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
115
    {
116
        return __atomic_compare_exchange_n
117
        (
118
            &storage, &expected, desired, false,
119
            atomics::detail::convert_memory_order_to_gcc(success_order),
120
            atomics::detail::convert_memory_order_to_gcc(failure_order)
121
        );
122
    }
123

    
124
    static BOOST_FORCEINLINE bool compare_exchange_weak(
125
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
126
    {
127
        return __atomic_compare_exchange_n
128
        (
129
            &storage, &expected, desired, true,
130
            atomics::detail::convert_memory_order_to_gcc(success_order),
131
            atomics::detail::convert_memory_order_to_gcc(failure_order)
132
        );
133
    }
134

    
135
    static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
136
    {
137
        return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
138
    }
139

    
140
    static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
141
    {
142
        return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
143
    }
144

    
145
    static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
146
    {
147
        return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
148
    }
149

    
150
    static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
151
    {
152
        return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order));
153
    }
154

    
155
    static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
156
    {
157
        __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order));
158
    }
159

    
160
    static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT
161
    {
162
        return __atomic_is_lock_free(sizeof(storage_type), &storage);
163
    }
164
};
165

    
166
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
167
#if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
168

    
169
// Workaround for clang bug: http://llvm.org/bugs/show_bug.cgi?id=19149
170
// Clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
171
template< bool Signed >
172
struct operations< 16u, Signed > :
173
    public cas_based_operations< gcc_dcas_x86_64< Signed > >
174
{
175
};
176

    
177
#else
178

    
179
template< bool Signed >
180
struct operations< 16u, Signed > :
181
    public gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >
182
{
183
    typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
184
};
185

    
186
#endif
187
#endif
188

    
189

    
190
#if BOOST_ATOMIC_INT64_LOCK_FREE > 0
191
#if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
192

    
193
// Workaround for clang bug http://llvm.org/bugs/show_bug.cgi?id=19355
194
template< bool Signed >
195
struct operations< 8u, Signed > :
196
    public cas_based_operations< gcc_dcas_x86< Signed > >
197
{
198
};
199

    
200
#elif (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
201
    (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
202
    (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
203
    (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
204
    (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
205

    
206
#define BOOST_ATOMIC_DETAIL_INT64_EXTENDED
207

    
208
template< bool Signed >
209
struct operations< 8u, Signed > :
210
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 8u, Signed >
211
{
212
    typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
213
};
214

    
215
#else
216

    
217
template< bool Signed >
218
struct operations< 8u, Signed > :
219
    public gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >
220
{
221
    typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
222
};
223

    
224
#endif
225
#endif
226

    
227
#if BOOST_ATOMIC_INT32_LOCK_FREE > 0
228
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
229
    (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
230
    (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
231
    (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
232
    (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
233

    
234
#define BOOST_ATOMIC_DETAIL_INT32_EXTENDED
235

    
236
#if !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
237

    
238
template< bool Signed >
239
struct operations< 4u, Signed > :
240
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 4u, Signed >
241
{
242
    typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
243
};
244

    
245
#else // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
246

    
247
template< bool Signed >
248
struct operations< 4u, Signed > :
249
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 4u, Signed >
250
{
251
    typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
252
};
253

    
254
#endif // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
255

    
256
#else
257

    
258
template< bool Signed >
259
struct operations< 4u, Signed > :
260
    public gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >
261
{
262
    typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
263
};
264

    
265
#endif
266
#endif
267

    
268
#if BOOST_ATOMIC_INT16_LOCK_FREE > 0
269
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
270
    (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
271
    (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
272
    (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
273
    (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE)
274

    
275
#define BOOST_ATOMIC_DETAIL_INT16_EXTENDED
276

    
277
#if !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED)
278

    
279
template< bool Signed >
280
struct operations< 2u, Signed > :
281
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 2u, Signed >
282
{
283
    typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
284
};
285

    
286
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
287

    
288
template< bool Signed >
289
struct operations< 2u, Signed > :
290
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 2u, Signed >
291
{
292
    typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
293
};
294

    
295
#else
296

    
297
template< bool Signed >
298
struct operations< 2u, Signed > :
299
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 2u, Signed >
300
{
301
    typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
302
};
303

    
304
#endif
305

    
306
#else
307

    
308
template< bool Signed >
309
struct operations< 2u, Signed > :
310
    public gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >
311
{
312
    typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
313
};
314

    
315
#endif
316
#endif
317

    
318
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
319
#if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\
320
    (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\
321
    (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\
322
    (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\
323
    (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) ||\
324
    (__GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE) ||\
325
    (__GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE)
326

    
327
#if !defined(BOOST_ATOMIC_DETAIL_INT16_EXTENDED)
328

    
329
template< bool Signed >
330
struct operations< 1u, Signed > :
331
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >, 1u, Signed >
332
{
333
    typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type;
334
};
335

    
336
#elif !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED)
337

    
338
template< bool Signed >
339
struct operations< 1u, Signed > :
340
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 1u, Signed >
341
{
342
    typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
343
};
344

    
345
#elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED)
346

    
347
template< bool Signed >
348
struct operations< 1u, Signed > :
349
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 1u, Signed >
350
{
351
    typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
352
};
353

    
354
#else
355

    
356
template< bool Signed >
357
struct operations< 1u, Signed > :
358
    public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 1u, Signed >
359
{
360
    typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
361
};
362

    
363
#endif
364

    
365
#else
366

    
367
template< bool Signed >
368
struct operations< 1u, Signed > :
369
    public gcc_atomic_operations< typename make_storage_type< 1u, Signed >::type >
370
{
371
    typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type;
372
};
373

    
374
#endif
375
#endif
376

    
377
#undef BOOST_ATOMIC_DETAIL_INT16_EXTENDED
378
#undef BOOST_ATOMIC_DETAIL_INT32_EXTENDED
379
#undef BOOST_ATOMIC_DETAIL_INT64_EXTENDED
380

    
381
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
382
{
383
    __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order));
384
}
385

    
386
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
387
{
388
    __atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order));
389
}
390

    
391
} // namespace detail
392
} // namespace atomics
393
} // namespace boost
394

    
395
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_