blob: ccd8d78d3d71c963635e4f348caf01be431b31c9 [file] [log] [blame]
Eric Fiseliereb2ff932016-01-19 21:58:49 +00001//===----------------------------------------------------------------------===////
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
Eric Fiselier1faf2892015-07-07 00:27:16 +000010#ifndef ATOMIC_SUPPORT_H
11#define ATOMIC_SUPPORT_H
12
13#include "__config"
14#include "memory" // for __libcpp_relaxed_load
15
16#if defined(__clang__) && __has_builtin(__atomic_load_n) \
17 && __has_builtin(__atomic_store_n) \
18 && __has_builtin(__atomic_add_fetch) \
Weiming Zhaofbfaec72017-09-19 23:18:03 +000019 && __has_builtin(__atomic_exchange_n) \
Eric Fiselier1faf2892015-07-07 00:27:16 +000020 && __has_builtin(__atomic_compare_exchange_n) \
21 && defined(__ATOMIC_RELAXED) \
22 && defined(__ATOMIC_CONSUME) \
23 && defined(__ATOMIC_ACQUIRE) \
24 && defined(__ATOMIC_RELEASE) \
25 && defined(__ATOMIC_ACQ_REL) \
26 && defined(__ATOMIC_SEQ_CST)
27# define _LIBCPP_HAS_ATOMIC_BUILTINS
28#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
29# define _LIBCPP_HAS_ATOMIC_BUILTINS
30#endif
31
32#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
Eric Fiselier0c6e7ae2017-05-10 21:40:58 +000033# if defined(_LIBCPP_WARNING)
Eric Fiselier1faf2892015-07-07 00:27:16 +000034 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
35# else
36# warning Building libc++ without __atomic builtins is unsupported
37# endif
38#endif
39
40_LIBCPP_BEGIN_NAMESPACE_STD
41
42namespace {
43
44#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
45
46enum __libcpp_atomic_order {
47 _AO_Relaxed = __ATOMIC_RELAXED,
48 _AO_Consume = __ATOMIC_CONSUME,
Ben Craig8ddd3ef2016-08-02 13:43:48 +000049 _AO_Acquire = __ATOMIC_ACQUIRE,
Eric Fiselier1faf2892015-07-07 00:27:16 +000050 _AO_Release = __ATOMIC_RELEASE,
51 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
52 _AO_Seq = __ATOMIC_SEQ_CST
53};
54
55template <class _ValueType, class _FromType>
56inline _LIBCPP_INLINE_VISIBILITY
57void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
58 int __order = _AO_Seq)
59{
60 __atomic_store_n(__dest, __val, __order);
61}
62
63template <class _ValueType, class _FromType>
64inline _LIBCPP_INLINE_VISIBILITY
65void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
66{
67 __atomic_store_n(__dest, __val, _AO_Relaxed);
68}
69
70template <class _ValueType>
71inline _LIBCPP_INLINE_VISIBILITY
72_ValueType __libcpp_atomic_load(_ValueType const* __val,
73 int __order = _AO_Seq)
74{
75 return __atomic_load_n(__val, __order);
76}
77
78template <class _ValueType, class _AddType>
79inline _LIBCPP_INLINE_VISIBILITY
80_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
81 int __order = _AO_Seq)
82{
83 return __atomic_add_fetch(__val, __a, __order);
84}
85
86template <class _ValueType>
87inline _LIBCPP_INLINE_VISIBILITY
Weiming Zhaofbfaec72017-09-19 23:18:03 +000088_ValueType __libcpp_atomic_exchange(_ValueType* __target,
89 _ValueType __value, int __order = _AO_Seq)
90{
91 return __atomic_exchange_n(__target, __value, __order);
92}
93
94template <class _ValueType>
95inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier1faf2892015-07-07 00:27:16 +000096bool __libcpp_atomic_compare_exchange(_ValueType* __val,
97 _ValueType* __expected, _ValueType __after,
98 int __success_order = _AO_Seq,
99 int __fail_order = _AO_Seq)
100{
101 return __atomic_compare_exchange_n(__val, __expected, __after, true,
102 __success_order, __fail_order);
103}
104
105#else // _LIBCPP_HAS_NO_THREADS
106
107enum __libcpp_atomic_order {
108 _AO_Relaxed,
109 _AO_Consume,
110 _AO_Acquire,
111 _AO_Release,
112 _AO_Acq_Rel,
113 _AO_Seq
114};
115
116template <class _ValueType, class _FromType>
117inline _LIBCPP_INLINE_VISIBILITY
118void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
119 int = 0)
120{
121 *__dest = __val;
122}
123
Dimitry Andric66aa3a72015-09-22 18:55:37 +0000124template <class _ValueType, class _FromType>
125inline _LIBCPP_INLINE_VISIBILITY
126void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
127{
128 *__dest = __val;
129}
130
Eric Fiselier1faf2892015-07-07 00:27:16 +0000131template <class _ValueType>
132inline _LIBCPP_INLINE_VISIBILITY
133_ValueType __libcpp_atomic_load(_ValueType const* __val,
134 int = 0)
135{
136 return *__val;
137}
138
139template <class _ValueType, class _AddType>
140inline _LIBCPP_INLINE_VISIBILITY
141_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
142 int = 0)
143{
144 return *__val += __a;
145}
146
147template <class _ValueType>
148inline _LIBCPP_INLINE_VISIBILITY
Weiming Zhaofbfaec72017-09-19 23:18:03 +0000149_ValueType __libcpp_atomic_exchange(_ValueType* __target,
150 _ValueType __value, int __order = _AO_Seq)
151{
152 _ValueType old = *__target;
153 *__target = __value;
154 return old;
155}
156
157template <class _ValueType>
158inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier1faf2892015-07-07 00:27:16 +0000159bool __libcpp_atomic_compare_exchange(_ValueType* __val,
160 _ValueType* __expected, _ValueType __after,
161 int = 0, int = 0)
162{
163 if (*__val == *__expected) {
164 *__val = __after;
165 return true;
166 }
167 *__expected = *__val;
168 return false;
169}
170
171#endif // _LIBCPP_HAS_NO_THREADS
172
173} // end namespace
174
175_LIBCPP_END_NAMESPACE_STD
176
177#endif // ATOMIC_SUPPORT_H