| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef _CUDA_ATOMIC |
| | #define _CUDA_ATOMIC |
| |
|
| | #ifndef __CUDACC_RTC__ |
| | #include <atomic> |
| | static_assert(ATOMIC_BOOL_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_CHAR_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_SHORT_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_INT_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_LONG_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_LLONG_LOCK_FREE == 2, ""); |
| | static_assert(ATOMIC_POINTER_LOCK_FREE == 2, ""); |
| | #undef ATOMIC_BOOL_LOCK_FREE |
| | #undef ATOMIC_BOOL_LOCK_FREE |
| | #undef ATOMIC_CHAR_LOCK_FREE |
| | #undef ATOMIC_CHAR16_T_LOCK_FREE |
| | #undef ATOMIC_CHAR32_T_LOCK_FREE |
| | #undef ATOMIC_WCHAR_T_LOCK_FREE |
| | #undef ATOMIC_SHORT_LOCK_FREE |
| | #undef ATOMIC_INT_LOCK_FREE |
| | #undef ATOMIC_LONG_LOCK_FREE |
| | #undef ATOMIC_LLONG_LOCK_FREE |
| | #undef ATOMIC_POINTER_LOCK_FREE |
| | #undef ATOMIC_FLAG_INIT |
| | #undef ATOMIC_VAR_INIT |
| | #endif |
| |
|
| | |
| | #ifndef _LIBCUDACXX_ATOMIC_IS_LOCK_FREE |
| | #define _LIBCUDACXX_ATOMIC_IS_LOCK_FREE(__x) (__x <= 8) |
| | #endif |
| |
|
| | #include "cassert" |
| | #include "cstddef" |
| | #include "cstdint" |
| | #include "type_traits" |
| | #include "version" |
| |
|
| | #include "detail/__config" |
| |
|
| | #include "detail/__pragma_push" |
| |
|
| | #include "detail/__threading_support" |
| |
|
| | #include "detail/libcxx/include/atomic" |
| |
|
| | _LIBCUDACXX_BEGIN_NAMESPACE_CUDA |
| |
|
| | using std::__detail::thread_scope; |
| | using std::__detail::thread_scope_system; |
| | using std::__detail::thread_scope_device; |
| | using std::__detail::thread_scope_block; |
| | using std::__detail::thread_scope_thread; |
| |
|
| | namespace __detail { |
| | using std::__detail::__thread_scope_block_tag; |
| | using std::__detail::__thread_scope_device_tag; |
| | using std::__detail::__thread_scope_system_tag; |
| | } |
| |
|
| | using memory_order = std::memory_order; |
| |
|
| | constexpr memory_order memory_order_relaxed = std::memory_order_relaxed; |
| | constexpr memory_order memory_order_consume = std::memory_order_consume; |
| | constexpr memory_order memory_order_acquire = std::memory_order_acquire; |
| | constexpr memory_order memory_order_release = std::memory_order_release; |
| | constexpr memory_order memory_order_acq_rel = std::memory_order_acq_rel; |
| | constexpr memory_order memory_order_seq_cst = std::memory_order_seq_cst; |
| |
|
| | |
| |
|
| | template <class _Tp, thread_scope _Sco = thread_scope::thread_scope_system> |
| | struct atomic |
| | : public std::__atomic_base<_Tp, _Sco> |
| | { |
| | typedef std::__atomic_base<_Tp, _Sco> __base; |
| |
|
| | constexpr atomic() noexcept = default; |
| | __host__ __device__ |
| | constexpr atomic(_Tp __d) noexcept : __base(__d) {} |
| |
|
| | __host__ __device__ |
| | _Tp operator=(_Tp __d) volatile noexcept |
| | {__base::store(__d); return __d;} |
| | __host__ __device__ |
| | _Tp operator=(_Tp __d) noexcept |
| | {__base::store(__d); return __d;} |
| |
|
| | __host__ __device__ |
| | _Tp fetch_max(const _Tp & __op, memory_order __m = memory_order_seq_cst) volatile noexcept |
| | { |
| | return std::__detail::__cxx_atomic_fetch_max(&this->__a_, __op, __m); |
| | } |
| |
|
| | __host__ __device__ |
| | _Tp fetch_min(const _Tp & __op, memory_order __m = memory_order_seq_cst) volatile noexcept |
| | { |
| | return std::__detail::__cxx_atomic_fetch_min(&this->__a_, __op, __m); |
| | } |
| | }; |
| |
|
| | |
| |
|
| | template <class _Tp, thread_scope _Sco> |
| | struct atomic<_Tp*, _Sco> |
| | : public std::__atomic_base<_Tp*, _Sco> |
| | { |
| | typedef std::__atomic_base<_Tp*, _Sco> __base; |
| |
|
| | constexpr atomic() noexcept = default; |
| | __host__ __device__ |
| | constexpr atomic(_Tp* __d) noexcept : __base(__d) {} |
| |
|
| | __host__ __device__ |
| | _Tp* operator=(_Tp* __d) volatile noexcept |
| | {__base::store(__d); return __d;} |
| | __host__ __device__ |
| | _Tp* operator=(_Tp* __d) noexcept |
| | {__base::store(__d); return __d;} |
| |
|
| | __host__ __device__ |
| | _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) |
| | volatile noexcept |
| | {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) noexcept |
| | {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) |
| | volatile noexcept |
| | {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) noexcept |
| | {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} |
| |
|
| | __host__ __device__ |
| | _Tp* operator++(int) volatile noexcept {return fetch_add(1);} |
| | __host__ __device__ |
| | _Tp* operator++(int) noexcept {return fetch_add(1);} |
| | __host__ __device__ |
| | _Tp* operator--(int) volatile noexcept {return fetch_sub(1);} |
| | __host__ __device__ |
| | _Tp* operator--(int) noexcept {return fetch_sub(1);} |
| | __host__ __device__ |
| | _Tp* operator++() volatile noexcept {return fetch_add(1) + 1;} |
| | __host__ __device__ |
| | _Tp* operator++() noexcept {return fetch_add(1) + 1;} |
| | __host__ __device__ |
| | _Tp* operator--() volatile noexcept {return fetch_sub(1) - 1;} |
| | __host__ __device__ |
| | _Tp* operator--() noexcept {return fetch_sub(1) - 1;} |
| | __host__ __device__ |
| | _Tp* operator+=(ptrdiff_t __op) volatile noexcept {return fetch_add(__op) + __op;} |
| | __host__ __device__ |
| | _Tp* operator+=(ptrdiff_t __op) noexcept {return fetch_add(__op) + __op;} |
| | __host__ __device__ |
| | _Tp* operator-=(ptrdiff_t __op) volatile noexcept {return fetch_sub(__op) - __op;} |
| | __host__ __device__ |
| | _Tp* operator-=(ptrdiff_t __op) noexcept {return fetch_sub(__op) - __op;} |
| | }; |
| |
|
| | |
| |
|
| | template <class _Tp, thread_scope _Sco = thread_scope::thread_scope_system> |
| | struct atomic_ref |
| | : public std::__atomic_base_ref<_Tp, _Sco> |
| | { |
| | typedef std::__atomic_base_ref<_Tp, _Sco> __base; |
| |
|
| | __host__ __device__ |
| | constexpr atomic_ref(_Tp& __d) noexcept : __base(__d) {} |
| |
|
| | __host__ __device__ |
| | _Tp operator=(_Tp __d) const volatile noexcept |
| | {__base::store(__d); return __d;} |
| | __host__ __device__ |
| | _Tp operator=(_Tp __d) const noexcept |
| | {__base::store(__d); return __d;} |
| |
|
| | __host__ __device__ |
| | _Tp fetch_max(const _Tp & __op, memory_order __m = memory_order_seq_cst) const volatile noexcept |
| | { |
| | return std::__detail::__cxx_atomic_fetch_max(&this->__a_, __op, __m); |
| | } |
| |
|
| | __host__ __device__ |
| | _Tp fetch_min(const _Tp & __op, memory_order __m = memory_order_seq_cst) const volatile noexcept |
| | { |
| | return std::__detail::__cxx_atomic_fetch_min(&this->__a_, __op, __m); |
| | } |
| | }; |
| |
|
| | |
| |
|
| | template <class _Tp, thread_scope _Sco> |
| | struct atomic_ref<_Tp*, _Sco> |
| | : public std::__atomic_base_ref<_Tp*, _Sco> |
| | { |
| | typedef std::__atomic_base_ref<_Tp*, _Sco> __base; |
| |
|
| | __host__ __device__ |
| | constexpr atomic_ref(_Tp*& __d) noexcept : __base(__d) {} |
| |
|
| | __host__ __device__ |
| | _Tp* operator=(_Tp* __d) const volatile noexcept |
| | {__base::store(__d); return __d;} |
| | __host__ __device__ |
| | _Tp* operator=(_Tp* __d) const noexcept |
| | {__base::store(__d); return __d;} |
| |
|
| | __host__ __device__ |
| | _Tp* fetch_add(ptrdiff_t __op, |
| | memory_order __m = memory_order_seq_cst) const volatile noexcept |
| | {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_add(ptrdiff_t __op, |
| | memory_order __m = memory_order_seq_cst) const noexcept |
| | {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_sub(ptrdiff_t __op, |
| | memory_order __m = memory_order_seq_cst) const volatile noexcept |
| | {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} |
| | __host__ __device__ |
| | _Tp* fetch_sub(ptrdiff_t __op, |
| | memory_order __m = memory_order_seq_cst) const noexcept |
| | {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} |
| |
|
| | __host__ __device__ |
| | _Tp* operator++(int) const volatile noexcept {return fetch_add(1);} |
| | __host__ __device__ |
| | _Tp* operator++(int) const noexcept {return fetch_add(1);} |
| | __host__ __device__ |
| | _Tp* operator--(int) const volatile noexcept {return fetch_sub(1);} |
| | __host__ __device__ |
| | _Tp* operator--(int) const noexcept {return fetch_sub(1);} |
| | __host__ __device__ |
| | _Tp* operator++() const volatile noexcept {return fetch_add(1) + 1;} |
| | __host__ __device__ |
| | _Tp* operator++() const noexcept {return fetch_add(1) + 1;} |
| | __host__ __device__ |
| | _Tp* operator--() const volatile noexcept {return fetch_sub(1) - 1;} |
| | __host__ __device__ |
| | _Tp* operator--() const noexcept {return fetch_sub(1) - 1;} |
| | __host__ __device__ |
| | _Tp* operator+=(ptrdiff_t __op) const volatile noexcept {return fetch_add(__op) + __op;} |
| | __host__ __device__ |
| | _Tp* operator+=(ptrdiff_t __op) const noexcept {return fetch_add(__op) + __op;} |
| | __host__ __device__ |
| | _Tp* operator-=(ptrdiff_t __op) const volatile noexcept {return fetch_sub(__op) - __op;} |
| | __host__ __device__ |
| | _Tp* operator-=(ptrdiff_t __op) const noexcept {return fetch_sub(__op) - __op;} |
| | }; |
| |
|
| | inline __host__ __device__ void atomic_thread_fence(memory_order __m, thread_scope _Scope = thread_scope::thread_scope_system) { |
| | NV_DISPATCH_TARGET( |
| | NV_IS_DEVICE, ( |
| | switch(_Scope) { |
| | case thread_scope::thread_scope_system: |
| | std::__detail::__atomic_thread_fence_cuda((int)__m, __detail::__thread_scope_system_tag()); |
| | break; |
| | case thread_scope::thread_scope_device: |
| | std::__detail::__atomic_thread_fence_cuda((int)__m, __detail::__thread_scope_device_tag()); |
| | break; |
| | case thread_scope::thread_scope_block: |
| | std::__detail::__atomic_thread_fence_cuda((int)__m, __detail::__thread_scope_block_tag()); |
| | break; |
| | } |
| | ), |
| | NV_IS_HOST, ( |
| | (void) _Scope; |
| | std::atomic_thread_fence(__m); |
| | ) |
| | ) |
| | } |
| |
|
| | inline __host__ __device__ void atomic_signal_fence(memory_order __m) { |
| | std::atomic_signal_fence(__m); |
| | } |
| |
|
| | _LIBCUDACXX_END_NAMESPACE_CUDA |
| |
|
| | #include "detail/__pragma_pop" |
| |
|
| | #endif |
| |
|