mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42: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:
parent
983439076b
commit
8efc22bd45
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user