|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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 |
|
|