blob: af0f5f505ea546b7d234f1b20fd58405f550c0ac [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) \
19 && __has_builtin(__atomic_compare_exchange_n) \
20 && defined(__ATOMIC_RELAXED) \
21 && defined(__ATOMIC_CONSUME) \
22 && defined(__ATOMIC_ACQUIRE) \
23 && defined(__ATOMIC_RELEASE) \
24 && defined(__ATOMIC_ACQ_REL) \
25 && defined(__ATOMIC_SEQ_CST)
26# define _LIBCPP_HAS_ATOMIC_BUILTINS
27#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
28# define _LIBCPP_HAS_ATOMIC_BUILTINS
29#endif
30
31#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
32# if defined(_MSC_VER) && !defined(__clang__)
33 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
34# else
35# warning Building libc++ without __atomic builtins is unsupported
36# endif
37#endif
38
39_LIBCPP_BEGIN_NAMESPACE_STD
40
41namespace {
42
43#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
44
45enum __libcpp_atomic_order {
46 _AO_Relaxed = __ATOMIC_RELAXED,
47 _AO_Consume = __ATOMIC_CONSUME,
Ben Craig8ddd3ef2016-08-02 13:43:48 +000048 _AO_Acquire = __ATOMIC_ACQUIRE,
Eric Fiselier1faf2892015-07-07 00:27:16 +000049 _AO_Release = __ATOMIC_RELEASE,
50 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
51 _AO_Seq = __ATOMIC_SEQ_CST
52};
53
54template <class _ValueType, class _FromType>
55inline _LIBCPP_INLINE_VISIBILITY
56void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
57 int __order = _AO_Seq)
58{
59 __atomic_store_n(__dest, __val, __order);
60}
61
62template <class _ValueType, class _FromType>
63inline _LIBCPP_INLINE_VISIBILITY
64void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
65{
66 __atomic_store_n(__dest, __val, _AO_Relaxed);
67}
68
69template <class _ValueType>
70inline _LIBCPP_INLINE_VISIBILITY
71_ValueType __libcpp_atomic_load(_ValueType const* __val,
72 int __order = _AO_Seq)
73{
74 return __atomic_load_n(__val, __order);
75}
76
77template <class _ValueType, class _AddType>
78inline _LIBCPP_INLINE_VISIBILITY
79_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
80 int __order = _AO_Seq)
81{
82 return __atomic_add_fetch(__val, __a, __order);
83}
84
85template <class _ValueType>
86inline _LIBCPP_INLINE_VISIBILITY
87bool __libcpp_atomic_compare_exchange(_ValueType* __val,
88 _ValueType* __expected, _ValueType __after,
89 int __success_order = _AO_Seq,
90 int __fail_order = _AO_Seq)
91{
92 return __atomic_compare_exchange_n(__val, __expected, __after, true,
93 __success_order, __fail_order);
94}
95
96#else // _LIBCPP_HAS_NO_THREADS
97
98enum __libcpp_atomic_order {
99 _AO_Relaxed,
100 _AO_Consume,
101 _AO_Acquire,
102 _AO_Release,
103 _AO_Acq_Rel,
104 _AO_Seq
105};
106
107template <class _ValueType, class _FromType>
108inline _LIBCPP_INLINE_VISIBILITY
109void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
110 int = 0)
111{
112 *__dest = __val;
113}
114
Dimitry Andric66aa3a72015-09-22 18:55:37 +0000115template <class _ValueType, class _FromType>
116inline _LIBCPP_INLINE_VISIBILITY
117void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
118{
119 *__dest = __val;
120}
121
Eric Fiselier1faf2892015-07-07 00:27:16 +0000122template <class _ValueType>
123inline _LIBCPP_INLINE_VISIBILITY
124_ValueType __libcpp_atomic_load(_ValueType const* __val,
125 int = 0)
126{
127 return *__val;
128}
129
130template <class _ValueType, class _AddType>
131inline _LIBCPP_INLINE_VISIBILITY
132_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
133 int = 0)
134{
135 return *__val += __a;
136}
137
138template <class _ValueType>
139inline _LIBCPP_INLINE_VISIBILITY
140bool __libcpp_atomic_compare_exchange(_ValueType* __val,
141 _ValueType* __expected, _ValueType __after,
142 int = 0, int = 0)
143{
144 if (*__val == *__expected) {
145 *__val = __after;
146 return true;
147 }
148 *__expected = *__val;
149 return false;
150}
151
152#endif // _LIBCPP_HAS_NO_THREADS
153
154} // end namespace
155
156_LIBCPP_END_NAMESPACE_STD
157
158#endif // ATOMIC_SUPPORT_H