mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-14 10:48:36 +12:00
Implement atomic_t<>::release
More relaxed store with release memory order
This commit is contained in:
parent
50922faac9
commit
2b66abaf10
4 changed files with 60 additions and 26 deletions
|
@ -4,7 +4,7 @@
|
|||
#include <functional>
|
||||
|
||||
// Helper class, provides access to compiler-specific atomic intrinsics
|
||||
template<typename T, std::size_t Size = sizeof(T)>
|
||||
template <typename T, std::size_t Size = sizeof(T)>
|
||||
struct atomic_storage
|
||||
{
|
||||
static_assert(sizeof(T) <= 16 && sizeof(T) == alignof(T), "atomic_storage<> error: invalid type");
|
||||
|
@ -29,6 +29,11 @@ struct atomic_storage
|
|||
__atomic_store(&dest, &value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
__atomic_store(&dest, &value, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
T result;
|
||||
|
@ -176,7 +181,7 @@ struct atomic_storage
|
|||
|
||||
/* The rest: ugly MSVC intrinsics + inline asm implementations */
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
@ -200,6 +205,12 @@ struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
|||
_InterlockedExchange8((volatile char*)&dest, (char&)value);
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*(volatile char*)&dest = (char&)value;
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
char r = _InterlockedExchange8((volatile char*)&dest, (char&)value);
|
||||
|
@ -232,7 +243,7 @@ struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
|||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct atomic_storage<T, 2> : atomic_storage<T, 0>
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
@ -256,6 +267,12 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
|
|||
_InterlockedExchange16((volatile short*)&dest, (short&)value);
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*(volatile short*)&dest = (short&)value;
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
short r = _InterlockedExchange16((volatile short*)&dest, (short&)value);
|
||||
|
@ -324,7 +341,7 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
|
|||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct atomic_storage<T, 4> : atomic_storage<T, 0>
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
@ -348,6 +365,12 @@ struct atomic_storage<T, 4> : atomic_storage<T, 0>
|
|||
_InterlockedExchange((volatile long*)&dest, (long&)value);
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*(volatile long*)&dest = (long&)value;
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
long r = _InterlockedExchange((volatile long*)&dest, (long&)value);
|
||||
|
@ -423,7 +446,7 @@ struct atomic_storage<T, 4> : atomic_storage<T, 0>
|
|||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct atomic_storage<T, 8> : atomic_storage<T, 0>
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
@ -447,6 +470,12 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
|
|||
_InterlockedExchange64((volatile llong*)&dest, (llong&)value);
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*(volatile llong*)&dest = (llong&)value;
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
llong r = _InterlockedExchange64((volatile llong*)&dest, (llong&)value);
|
||||
|
@ -525,7 +554,7 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
|
|||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
@ -550,6 +579,14 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
|||
while (!_InterlockedCompareExchange128((volatile llong*)&dest, hi, lo, cmp));
|
||||
}
|
||||
|
||||
static inline void release(T& dest, T value)
|
||||
{
|
||||
llong lo = *(llong*)&value;
|
||||
llong hi = *((llong*)&value + 1);
|
||||
llong cmp[2]{ *(volatile llong*)&dest, *((volatile llong*)&dest + 1) };
|
||||
while (!_InterlockedCompareExchange128((volatile llong*)&dest, hi, lo, cmp));
|
||||
}
|
||||
|
||||
static inline T exchange(T& dest, T value)
|
||||
{
|
||||
llong lo = *(llong*)&value;
|
||||
|
@ -764,6 +801,12 @@ public:
|
|||
return rhs;
|
||||
}
|
||||
|
||||
// Atomically write data with release memory order (faster on x86)
|
||||
void release(const type& rhs)
|
||||
{
|
||||
atomic_storage<type>::release(m_data, rhs);
|
||||
}
|
||||
|
||||
// Atomically replace data with value, return previous data value
|
||||
type exchange(const type& rhs)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue