19729cf09SDimitry Andric //===----------------------------------------------------------------------===////
29729cf09SDimitry Andric //
39729cf09SDimitry Andric // The LLVM Compiler Infrastructure
49729cf09SDimitry Andric //
59729cf09SDimitry Andric // This file is dual licensed under the MIT and the University of Illinois Open
69729cf09SDimitry Andric // Source Licenses. See LICENSE.TXT for details.
79729cf09SDimitry Andric //
89729cf09SDimitry Andric //===----------------------------------------------------------------------===////
99729cf09SDimitry Andric
109729cf09SDimitry Andric #ifndef ATOMIC_SUPPORT_H
119729cf09SDimitry Andric #define ATOMIC_SUPPORT_H
129729cf09SDimitry Andric
139729cf09SDimitry Andric #include "__config"
149729cf09SDimitry Andric #include "memory" // for __libcpp_relaxed_load
159729cf09SDimitry Andric
169729cf09SDimitry Andric #if defined(__clang__) && __has_builtin(__atomic_load_n) \
179729cf09SDimitry Andric && __has_builtin(__atomic_store_n) \
189729cf09SDimitry Andric && __has_builtin(__atomic_add_fetch) \
19*b2c7081bSDimitry Andric && __has_builtin(__atomic_exchange_n) \
209729cf09SDimitry Andric && __has_builtin(__atomic_compare_exchange_n) \
219729cf09SDimitry Andric && defined(__ATOMIC_RELAXED) \
229729cf09SDimitry Andric && defined(__ATOMIC_CONSUME) \
239729cf09SDimitry Andric && defined(__ATOMIC_ACQUIRE) \
249729cf09SDimitry Andric && defined(__ATOMIC_RELEASE) \
259729cf09SDimitry Andric && defined(__ATOMIC_ACQ_REL) \
269729cf09SDimitry Andric && defined(__ATOMIC_SEQ_CST)
279729cf09SDimitry Andric # define _LIBCPP_HAS_ATOMIC_BUILTINS
289729cf09SDimitry Andric #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
299729cf09SDimitry Andric # define _LIBCPP_HAS_ATOMIC_BUILTINS
309729cf09SDimitry Andric #endif
319729cf09SDimitry Andric
329729cf09SDimitry Andric #if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
335517e702SDimitry Andric # if defined(_LIBCPP_WARNING)
349729cf09SDimitry Andric _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
359729cf09SDimitry Andric # else
369729cf09SDimitry Andric # warning Building libc++ without __atomic builtins is unsupported
379729cf09SDimitry Andric # endif
389729cf09SDimitry Andric #endif
399729cf09SDimitry Andric
409729cf09SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
419729cf09SDimitry Andric
429729cf09SDimitry Andric namespace {
439729cf09SDimitry Andric
449729cf09SDimitry Andric #if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
459729cf09SDimitry Andric
469729cf09SDimitry Andric enum __libcpp_atomic_order {
479729cf09SDimitry Andric _AO_Relaxed = __ATOMIC_RELAXED,
489729cf09SDimitry Andric _AO_Consume = __ATOMIC_CONSUME,
49aed8d94eSDimitry Andric _AO_Acquire = __ATOMIC_ACQUIRE,
509729cf09SDimitry Andric _AO_Release = __ATOMIC_RELEASE,
519729cf09SDimitry Andric _AO_Acq_Rel = __ATOMIC_ACQ_REL,
529729cf09SDimitry Andric _AO_Seq = __ATOMIC_SEQ_CST
539729cf09SDimitry Andric };
549729cf09SDimitry Andric
559729cf09SDimitry Andric template <class _ValueType, class _FromType>
569729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
579729cf09SDimitry Andric void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
589729cf09SDimitry Andric int __order = _AO_Seq)
599729cf09SDimitry Andric {
609729cf09SDimitry Andric __atomic_store_n(__dest, __val, __order);
619729cf09SDimitry Andric }
629729cf09SDimitry Andric
639729cf09SDimitry Andric template <class _ValueType, class _FromType>
649729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
__libcpp_relaxed_store(_ValueType * __dest,_FromType __val)659729cf09SDimitry Andric void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
669729cf09SDimitry Andric {
679729cf09SDimitry Andric __atomic_store_n(__dest, __val, _AO_Relaxed);
689729cf09SDimitry Andric }
699729cf09SDimitry Andric
709729cf09SDimitry Andric template <class _ValueType>
719729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
729729cf09SDimitry Andric _ValueType __libcpp_atomic_load(_ValueType const* __val,
739729cf09SDimitry Andric int __order = _AO_Seq)
749729cf09SDimitry Andric {
759729cf09SDimitry Andric return __atomic_load_n(__val, __order);
769729cf09SDimitry Andric }
779729cf09SDimitry Andric
789729cf09SDimitry Andric template <class _ValueType, class _AddType>
799729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
809729cf09SDimitry Andric _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
819729cf09SDimitry Andric int __order = _AO_Seq)
829729cf09SDimitry Andric {
839729cf09SDimitry Andric return __atomic_add_fetch(__val, __a, __order);
849729cf09SDimitry Andric }
859729cf09SDimitry Andric
869729cf09SDimitry Andric template <class _ValueType>
879729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
88*b2c7081bSDimitry Andric _ValueType __libcpp_atomic_exchange(_ValueType* __target,
89*b2c7081bSDimitry Andric _ValueType __value, int __order = _AO_Seq)
90*b2c7081bSDimitry Andric {
91*b2c7081bSDimitry Andric return __atomic_exchange_n(__target, __value, __order);
92*b2c7081bSDimitry Andric }
93*b2c7081bSDimitry Andric
94*b2c7081bSDimitry Andric template <class _ValueType>
95*b2c7081bSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
969729cf09SDimitry Andric bool __libcpp_atomic_compare_exchange(_ValueType* __val,
979729cf09SDimitry Andric _ValueType* __expected, _ValueType __after,
989729cf09SDimitry Andric int __success_order = _AO_Seq,
999729cf09SDimitry Andric int __fail_order = _AO_Seq)
1009729cf09SDimitry Andric {
1019729cf09SDimitry Andric return __atomic_compare_exchange_n(__val, __expected, __after, true,
1029729cf09SDimitry Andric __success_order, __fail_order);
1039729cf09SDimitry Andric }
1049729cf09SDimitry Andric
1059729cf09SDimitry Andric #else // _LIBCPP_HAS_NO_THREADS
1069729cf09SDimitry Andric
1079729cf09SDimitry Andric enum __libcpp_atomic_order {
1089729cf09SDimitry Andric _AO_Relaxed,
1099729cf09SDimitry Andric _AO_Consume,
1109729cf09SDimitry Andric _AO_Acquire,
1119729cf09SDimitry Andric _AO_Release,
1129729cf09SDimitry Andric _AO_Acq_Rel,
1139729cf09SDimitry Andric _AO_Seq
1149729cf09SDimitry Andric };
1159729cf09SDimitry Andric
1169729cf09SDimitry Andric template <class _ValueType, class _FromType>
1179729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
1189729cf09SDimitry Andric void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
1199729cf09SDimitry Andric int = 0)
1209729cf09SDimitry Andric {
1219729cf09SDimitry Andric *__dest = __val;
1229729cf09SDimitry Andric }
1239729cf09SDimitry Andric
1249729cf09SDimitry Andric template <class _ValueType, class _FromType>
1259729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
1269729cf09SDimitry Andric void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
1279729cf09SDimitry Andric {
1289729cf09SDimitry Andric *__dest = __val;
1299729cf09SDimitry Andric }
1309729cf09SDimitry Andric
1319729cf09SDimitry Andric template <class _ValueType>
1329729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
1339729cf09SDimitry Andric _ValueType __libcpp_atomic_load(_ValueType const* __val,
1349729cf09SDimitry Andric int = 0)
1359729cf09SDimitry Andric {
1369729cf09SDimitry Andric return *__val;
1379729cf09SDimitry Andric }
1389729cf09SDimitry Andric
1399729cf09SDimitry Andric template <class _ValueType, class _AddType>
1409729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
1419729cf09SDimitry Andric _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
1429729cf09SDimitry Andric int = 0)
1439729cf09SDimitry Andric {
1449729cf09SDimitry Andric return *__val += __a;
1459729cf09SDimitry Andric }
1469729cf09SDimitry Andric
1479729cf09SDimitry Andric template <class _ValueType>
1489729cf09SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
149*b2c7081bSDimitry Andric _ValueType __libcpp_atomic_exchange(_ValueType* __target,
150*b2c7081bSDimitry Andric _ValueType __value, int __order = _AO_Seq)
151*b2c7081bSDimitry Andric {
152*b2c7081bSDimitry Andric _ValueType old = *__target;
153*b2c7081bSDimitry Andric *__target = __value;
154*b2c7081bSDimitry Andric return old;
155*b2c7081bSDimitry Andric }
156*b2c7081bSDimitry Andric
157*b2c7081bSDimitry Andric template <class _ValueType>
158*b2c7081bSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
1599729cf09SDimitry Andric bool __libcpp_atomic_compare_exchange(_ValueType* __val,
1609729cf09SDimitry Andric _ValueType* __expected, _ValueType __after,
1619729cf09SDimitry Andric int = 0, int = 0)
1629729cf09SDimitry Andric {
1639729cf09SDimitry Andric if (*__val == *__expected) {
1649729cf09SDimitry Andric *__val = __after;
1659729cf09SDimitry Andric return true;
1669729cf09SDimitry Andric }
1679729cf09SDimitry Andric *__expected = *__val;
1689729cf09SDimitry Andric return false;
1699729cf09SDimitry Andric }
1709729cf09SDimitry Andric
1719729cf09SDimitry Andric #endif // _LIBCPP_HAS_NO_THREADS
1729729cf09SDimitry Andric
1739729cf09SDimitry Andric } // end namespace
1749729cf09SDimitry Andric
1759729cf09SDimitry Andric _LIBCPP_END_NAMESPACE_STD
1769729cf09SDimitry Andric
1779729cf09SDimitry Andric #endif // ATOMIC_SUPPORT_H
178