Adding new files
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
// File: crn_atomics.h
|
||||
#ifndef CRN_ATOMICS_H
|
||||
#define CRN_ATOMICS_H
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "crn_winhdr.h"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && CRNLIB_PLATFORM_PC
|
||||
extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void crnlib_yield_processor()
|
||||
{
|
||||
__asm__ __volatile__("pause");
|
||||
}
|
||||
#else
|
||||
CRNLIB_FORCE_INLINE void crnlib_yield_processor()
|
||||
{
|
||||
#if CRNLIB_USE_MSVC_INTRINSICS
|
||||
#if CRNLIB_PLATFORM_PC_X64
|
||||
_mm_pause();
|
||||
#else
|
||||
YieldProcessor();
|
||||
#endif
|
||||
#else
|
||||
// No implementation
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
|
||||
extern "C" __int64 _InterlockedCompareExchange64(__int64 volatile * Destination, __int64 Exchange, __int64 Comperand);
|
||||
#if defined(_MSC_VER)
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
#endif
|
||||
#endif // CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
|
||||
|
||||
namespace crnlib
|
||||
{
|
||||
#if CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
|
||||
typedef LONG atomic32_t;
|
||||
typedef LONGLONG atomic64_t;
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedCompareExchange(pDest, exchange, comparand);
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
|
||||
return _InterlockedCompareExchange64(pDest, exchange, comparand);
|
||||
}
|
||||
|
||||
// Returns the resulting incremented value.
|
||||
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedIncrement(pDest);
|
||||
}
|
||||
|
||||
// Returns the resulting decremented value.
|
||||
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedDecrement(pDest);
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedExchange(pDest, val);
|
||||
}
|
||||
|
||||
// Returns the resulting value.
|
||||
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedExchangeAdd(pDest, val) + val;
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return InterlockedExchangeAdd(pDest, val);
|
||||
}
|
||||
#elif CRNLIB_USE_GCC_ATOMIC_BUILTINS
|
||||
typedef long atomic32_t;
|
||||
typedef long long atomic64_t;
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_val_compare_and_swap(pDest, comparand, exchange);
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
|
||||
return __sync_val_compare_and_swap(pDest, comparand, exchange);
|
||||
}
|
||||
|
||||
// Returns the resulting incremented value.
|
||||
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_add_and_fetch(pDest, 1);
|
||||
}
|
||||
|
||||
// Returns the resulting decremented value.
|
||||
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_sub_and_fetch(pDest, 1);
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_lock_test_and_set(pDest, val);
|
||||
}
|
||||
|
||||
// Returns the resulting value.
|
||||
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_add_and_fetch(pDest, val);
|
||||
}
|
||||
|
||||
// Returns the original value.
|
||||
inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return __sync_fetch_and_add(pDest, val);
|
||||
}
|
||||
#else
|
||||
#define CRNLIB_NO_ATOMICS 1
|
||||
|
||||
// Atomic ops not supported - but try to do something reasonable. Assumes no threading at all.
|
||||
typedef long atomic32_t;
|
||||
typedef long long atomic64_t;
|
||||
|
||||
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
atomic32_t cur = *pDest;
|
||||
if (cur == comparand)
|
||||
*pDest = exchange;
|
||||
return cur;
|
||||
}
|
||||
|
||||
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
|
||||
atomic64_t cur = *pDest;
|
||||
if (cur == comparand)
|
||||
*pDest = exchange;
|
||||
return cur;
|
||||
}
|
||||
|
||||
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return (*pDest += 1);
|
||||
}
|
||||
|
||||
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return (*pDest -= 1);
|
||||
}
|
||||
|
||||
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
atomic32_t cur = *pDest;
|
||||
*pDest = val;
|
||||
return cur;
|
||||
}
|
||||
|
||||
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
return (*pDest += val);
|
||||
}
|
||||
|
||||
inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
|
||||
{
|
||||
CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
|
||||
atomic32_t cur = *pDest;
|
||||
*pDest += val;
|
||||
return cur;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace crnlib
|
||||
|
||||
#endif // CRN_ATOMICS_H
|
||||
Reference in New Issue
Block a user