1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

atomic.hpp: simplify and unify bit test instructions

Also make them available on all platform.
Rename some rare methods.
This commit is contained in:
Nekotekina 2020-12-03 14:47:15 +03:00
parent 983439076b
commit 8efc22bd45
4 changed files with 80 additions and 122 deletions

View File

@ -2228,7 +2228,7 @@ void thread_ctrl::_wait_for(u64 usec, bool alert /* true */)
}
#endif
if (_this->m_sync.btr(2))
if (_this->m_sync.bit_test_reset(2))
{
return;
}

View File

@ -205,7 +205,7 @@ constexpr bs_t<T> operator ^(T lhs, T rhs)
// Atomic bitset specialization with optimized operations
template <typename T>
class atomic_bs_t : public atomic_t<::bs_t<T>> // TODO: true specialization
class atomic_bs_t : public atomic_t<::bs_t<T>>
{
// Corresponding bitset type
using bs_t = ::bs_t<T>;
@ -379,11 +379,6 @@ public:
return lhs.m_data != rhs.load().m_data;
}
bool test(const bs_t& rhs)
{
return base::load().test(rhs);
}
bool test_and_set(T rhs)
{
return atomic_storage<under>::bts(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
@ -394,10 +389,14 @@ public:
return atomic_storage<under>::btr(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
}
bool test_and_complement(T rhs)
bool test_and_invert(T rhs)
{
return atomic_storage<under>::btc(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
}
bool bit_test_set(uint bit) = delete;
bool bit_test_reset(uint bit) = delete;
bool bit_test_invert(uint bit) = delete;
};
template <typename T>

View File

@ -604,7 +604,7 @@ s32 _spurs::detach_lv2_eq(vm::ptr<CellSpurs> spurs, u8 spuPort, bool spursCreate
if (!spursCreated)
{
if (!spurs->spuPortBits.btr(spuPort) && _spurs::get_sdk_version() >= 0x180000)
if (!spurs->spuPortBits.bit_test_reset(spuPort) && _spurs::get_sdk_version() >= 0x180000)
{
return CELL_SPURS_CORE_ERROR_SRCH;
}
@ -1831,8 +1831,8 @@ s32 cellSpursSetPriority(vm::ptr<CellSpurs> spurs, u32 wid, u32 spuId, u32 prior
return CELL_SPURS_CORE_ERROR_STAT;
vm::light_op(spurs->wklInfo(wid).priority[spuId], [&](u8& v){ atomic_storage<u8>::release(v, priority); });
vm::light_op(spurs->sysSrvMsgUpdateWorkload, [&](atomic_t<u8>& v){ v.bts(spuId); });
vm::light_op(spurs->sysSrvMessage, [&](atomic_t<u8>& v){ v.bts(spuId); });
vm::light_op(spurs->sysSrvMsgUpdateWorkload, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
vm::light_op(spurs->sysSrvMessage, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
return CELL_OK;
}

View File

@ -416,34 +416,77 @@ struct atomic_storage
return atomic_storage<T>::sub_fetch(dest, 1);
}
static inline bool test_and_set(T& dest, T mask)
{
return (atomic_storage<T>::fetch_or(dest, mask) & mask) != 0;
}
static inline bool test_and_reset(T& dest, T mask)
{
return (atomic_storage<T>::fetch_and(dest, ~mask) & mask) != 0;
}
static inline bool test_and_complement(T& dest, T mask)
{
return (atomic_storage<T>::fetch_xor(dest, mask) & mask) != 0;
}
static inline bool bts(T& dest, uint bit)
{
return atomic_storage<T>::test_and_set(dest, static_cast<T>(1) << bit);
uchar* dst = reinterpret_cast<uchar*>(&dest);
if constexpr (sizeof(T) < 4)
{
const uptr ptr = reinterpret_cast<uptr>(dst);
// Align the bit up and pointer down
bit = bit + (ptr & 3) * 8;
dst = reinterpret_cast<T*>(ptr & -4);
}
#ifdef _MSC_VER
return _interlockedbittestandset((long*)dst, bit) != 0;
#else
bool result;
__asm__ volatile ("lock btsl %2, 0(%1)\n" : "=@ccc" (result) : "r" (dst), "Ir" (bit) : "cc", "memory");
return result;
#endif
}
static inline bool btr(T& dest, uint bit)
{
return atomic_storage<T>::test_and_reset(dest, static_cast<T>(1) << bit);
uchar* dst = reinterpret_cast<uchar*>(&dest);
if constexpr (sizeof(T) < 4)
{
const uptr ptr = reinterpret_cast<uptr>(dst);
// Align the bit up and pointer down
bit = bit + (ptr & 3) * 8;
dst = reinterpret_cast<T*>(ptr & -4);
}
#ifdef _MSC_VER
return _interlockedbittestandreset((long*)dst, bit) != 0;
#else
bool result;
__asm__ volatile ("lock btrl %2, 0(%1)\n" : "=@ccc" (result) : "r" (dst), "Ir" (bit) : "cc", "memory");
return result;
#endif
}
static inline bool btc(T& dest, uint bit)
{
return atomic_storage<T>::test_and_complement(dest, static_cast<T>(1) << bit);
uchar* dst = reinterpret_cast<uchar*>(&dest);
if constexpr (sizeof(T) < 4)
{
const uptr ptr = reinterpret_cast<uptr>(dst);
// Align the bit up and pointer down
bit = bit + (ptr & 3) * 8;
dst = reinterpret_cast<T*>(ptr & -4);
}
#ifdef _MSC_VER
while (true)
{
// Keep trying until we actually invert desired bit
if (!_bittest((long*)dst, bit) && !_interlockedbittestandset((long*)dst, bit))
return false;
if (_interlockedbittestandreset((long*)dst, bit))
return true;
}
#else
bool result;
__asm__ volatile ("lock btcl %2, 0(%1)\n" : "=@ccc" (result) : "r" (dst), "Ir" (bit) : "cc", "memory");
return result;
#endif
}
};
@ -586,30 +629,6 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
const short r = _InterlockedDecrement16(reinterpret_cast<volatile short*>(&dest));
return std::bit_cast<T>(r);
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
ushort _bit = static_cast<ushort>(bit);
__asm__("lock btsw %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
ushort _bit = static_cast<ushort>(bit);
__asm__("lock btrw %2, %0\n": "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
ushort _bit = static_cast<ushort>(bit);
__asm__("lock btcw %2, %0\n": "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
#endif
};
@ -700,37 +719,6 @@ struct atomic_storage<T, 4> : atomic_storage<T, 0>
const long r = _InterlockedDecrement(reinterpret_cast<volatile long*>(&dest));
return std::bit_cast<T>(r);
}
static inline bool bts(T& dest, uint bit)
{
return _interlockedbittestandset(reinterpret_cast<volatile long*>(&dest), bit) != 0;
}
static inline bool btr(T& dest, uint bit)
{
return _interlockedbittestandreset(reinterpret_cast<volatile long*>(&dest), bit) != 0;
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
__asm__("lock btsl %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
__asm__("lock btrl %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
__asm__("lock btcl %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (bit) : "cc");
return result;
}
#endif
};
@ -821,40 +809,6 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
const llong r = _InterlockedDecrement64(reinterpret_cast<volatile llong*>(&dest));
return std::bit_cast<T>(r);
}
static inline bool bts(T& dest, uint bit)
{
return _interlockedbittestandset64(reinterpret_cast<volatile llong*>(&dest), bit) != 0;
}
static inline bool btr(T& dest, uint bit)
{
return _interlockedbittestandreset64(reinterpret_cast<volatile llong*>(&dest), bit) != 0;
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
ullong _bit = bit;
__asm__("lock btsq %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
ullong _bit = bit;
__asm__("lock btrq %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
ullong _bit = bit;
__asm__("lock btcq %2, %0\n" : "+m" (dest), "=@ccc" (result) : "Ir" (_bit) : "cc");
return result;
}
#endif
};
@ -1431,14 +1385,19 @@ public:
}
}
bool bts(uint bit)
bool bit_test_set(uint bit)
{
return atomic_storage<type>::bts(m_data, bit);
return atomic_storage<type>::bts(m_data, bit & (sizeof(T) * 8 - 1));
}
bool btr(uint bit)
bool bit_test_reset(uint bit)
{
return atomic_storage<type>::btr(m_data, bit);
return atomic_storage<type>::btr(m_data, bit & (sizeof(T) * 8 - 1));
}
bool bit_test_invert(uint bit)
{
return atomic_storage<type>::btc(m_data, bit & (sizeof(T) * 8 - 1));
}
// Timeout is discouraged