mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 00:11:24 +12:00
Atomic intrinsics refactoring
This commit is contained in:
parent
b0da8319b7
commit
09fbda603c
3 changed files with 137 additions and 18 deletions
|
@ -303,6 +303,29 @@ union u128
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef InterlockedCompareExchange
|
||||||
|
static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 exch, u128 comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
auto res = __sync_val_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
|
||||||
|
return (u128&)res;
|
||||||
|
#else
|
||||||
|
u128 cmp = comp;
|
||||||
|
_InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&cmp);
|
||||||
|
return cmp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __forceinline bool InterlockedCompareExchangeTest(volatile u128* dest, u128 exch, u128 comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_bool_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
|
||||||
|
#else
|
||||||
|
return _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp) != 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define re16(val) _byteswap_ushort(val)
|
#define re16(val) _byteswap_ushort(val)
|
||||||
#define re32(val) _byteswap_ulong(val)
|
#define re32(val) _byteswap_ulong(val)
|
||||||
#define re64(val) _byteswap_uint64(val)
|
#define re64(val) _byteswap_uint64(val)
|
||||||
|
|
130
Utilities/GNU.h
130
Utilities/GNU.h
|
@ -46,23 +46,6 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize])
|
||||||
#define _byteswap_uint64(x) __builtin_bswap64(x)
|
#define _byteswap_uint64(x) __builtin_bswap64(x)
|
||||||
#define INFINITE 0xFFFFFFFF
|
#define INFINITE 0xFFFFFFFF
|
||||||
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
|
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
|
||||||
#define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
|
|
||||||
#define InterlockedExchange(ptr, value) __sync_lock_test_and_set(ptr, value)
|
|
||||||
#define InterlockedOr(ptr, value) __sync_fetch_and_or(ptr, value)
|
|
||||||
#define InterlockedAnd(ptr, value) __sync_fetch_and_and(ptr, value)
|
|
||||||
#define InterlockedXor(ptr, value) __sync_fetch_and_xor(ptr, value)
|
|
||||||
|
|
||||||
//inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val)
|
|
||||||
//{
|
|
||||||
// int64_t olderval;
|
|
||||||
// int64_t oldval = *dest;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// olderval = oldval;
|
|
||||||
// oldval = __sync_val_compare_and_swap(dest, olderval | val, olderval);
|
|
||||||
// } while (olderval != oldval);
|
|
||||||
// return oldval;
|
|
||||||
//}
|
|
||||||
|
|
||||||
inline uint64_t __umulh(uint64_t a, uint64_t b)
|
inline uint64_t __umulh(uint64_t a, uint64_t b)
|
||||||
{
|
{
|
||||||
|
@ -99,95 +82,208 @@ int clock_gettime(int foo, struct timespec *ts);
|
||||||
#ifndef InterlockedCompareExchange
|
#ifndef InterlockedCompareExchange
|
||||||
static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
|
static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
|
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
|
static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
|
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
|
static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
|
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
|
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
|
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static __forceinline bool InterlockedCompareExchangeTest(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
|
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static __forceinline bool InterlockedCompareExchangeTest(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
|
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static __forceinline bool InterlockedCompareExchangeTest(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
|
return _InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static __forceinline bool InterlockedCompareExchangeTest(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
|
||||||
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||||
|
#else
|
||||||
|
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef InterlockedExchange
|
#ifndef InterlockedExchange
|
||||||
static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value)
|
static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_lock_test_and_set(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedExchange8((volatile char*)dest, value);
|
return _InterlockedExchange8((volatile char*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value)
|
static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_lock_test_and_set(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedExchange16((volatile short*)dest, value);
|
return _InterlockedExchange16((volatile short*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value)
|
static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_lock_test_and_set(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedExchange((volatile long*)dest, value);
|
return _InterlockedExchange((volatile long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value)
|
static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_lock_test_and_set(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedExchange64((volatile long long*)dest, value);
|
return _InterlockedExchange64((volatile long long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef InterlockedOr
|
#ifndef InterlockedOr
|
||||||
static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value)
|
static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_or(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedOr8((volatile char*)dest, value);
|
return _InterlockedOr8((volatile char*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value)
|
static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_or(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedOr16((volatile short*)dest, value);
|
return _InterlockedOr16((volatile short*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value)
|
static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_or(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedOr((volatile long*)dest, value);
|
return _InterlockedOr((volatile long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value)
|
static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_or(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedOr64((volatile long long*)dest, value);
|
return _InterlockedOr64((volatile long long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef InterlockedAnd
|
#ifndef InterlockedAnd
|
||||||
static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value)
|
static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_and(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedAnd8((volatile char*)dest, value);
|
return _InterlockedAnd8((volatile char*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value)
|
static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_and(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedAnd16((volatile short*)dest, value);
|
return _InterlockedAnd16((volatile short*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value)
|
static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_and(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedAnd((volatile long*)dest, value);
|
return _InterlockedAnd((volatile long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value)
|
static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_and(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedAnd64((volatile long long*)dest, value);
|
return _InterlockedAnd64((volatile long long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef InterlockedXor
|
#ifndef InterlockedXor
|
||||||
static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value)
|
static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_xor(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedXor8((volatile char*)dest, value);
|
return _InterlockedXor8((volatile char*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value)
|
static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_xor(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedXor16((volatile short*)dest, value);
|
return _InterlockedXor16((volatile short*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value)
|
static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_xor(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedXor((volatile long*)dest, value);
|
return _InterlockedXor((volatile long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value)
|
static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
return __sync_fetch_and_xor(dest, value);
|
||||||
|
#else
|
||||||
return _InterlockedXor64((volatile long long*)dest, value);
|
return _InterlockedXor64((volatile long long*)dest, value);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
// atomically compare data with cmp, replace with exch if equal, return true if data was replaced
|
// atomically compare data with cmp, replace with exch if equal, return true if data was replaced
|
||||||
__forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile
|
__forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile
|
||||||
{
|
{
|
||||||
return InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)) == (atomic_type&)(cmp);
|
return InterlockedCompareExchangeTest(&data, (atomic_type&)(exch), (atomic_type&)(cmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// read data with memory barrier
|
// read data with memory barrier
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue