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

atomic_t: cleanup type requirements

Add C++17 requirements.
Remove alignment requirements (auto-align type).
What's missing is to detect padding and forbid it.
This commit is contained in:
Nekotekina 2020-12-04 18:03:50 +03:00
parent 8efc22bd45
commit d1e7837422
6 changed files with 38 additions and 20 deletions

View File

@ -539,6 +539,12 @@ struct alignas(16) s128
CHECK_SIZE_ALIGN(u128, 16, 16);
CHECK_SIZE_ALIGN(s128, 16, 16);
template <>
struct get_int_impl<16>
{
using utype = u128;
};
// Return magic value for any unsigned type
constexpr inline struct umax_helper
{

View File

@ -38,7 +38,7 @@ enum
CELL_AUDIO_BLOCK_SAMPLES = 256,
CELL_AUDIO_CREATEEVENTFLAG_SPU = 0x00000001,
CELL_AUDIO_EVENT_MIX = 0,
CELL_AUDIO_EVENT_HEADPHONE = 1,
@ -144,7 +144,7 @@ struct audio_port
u32 size;
u64 timestamp; // copy of global timestamp
struct alignas(8) level_set_t
struct level_set_t
{
float value;
float inc;

View File

@ -410,7 +410,7 @@ bool squeue_test_exit();
template<typename T, u32 sq_size = 256>
class squeue_t
{
struct alignas(8) squeue_sync_var_t
struct squeue_sync_var_t
{
struct
{

View File

@ -692,7 +692,7 @@ struct alignas(128) CellSpurs
u8 xCA; // 0xCA
u8 xCB; // 0xCB
struct alignas(4) SrvTraceSyncVar
struct SrvTraceSyncVar
{
u8 sysSrvTraceInitialised; // 0xCC
u8 sysSrvNotifyUpdateTraceComplete; // 0xCD
@ -881,7 +881,7 @@ CHECK_SIZE_ALIGN(CellSpursWorkloadAttribute, 512, 8);
struct alignas(128) CellSpursEventFlag
{
struct alignas(8) ControlSyncVar
struct ControlSyncVar
{
be_t<u16> events; // 0x00 Event bits
be_t<u16> spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks

View File

@ -36,7 +36,7 @@ enum CellSyncError1 : u32
struct CellSyncMutex
{
struct alignas(4) Counter
struct Counter
{
be_t<u16> rel;
be_t<u16> acq;
@ -162,7 +162,7 @@ CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16);
struct alignas(32) CellSyncQueue
{
struct alignas(8) ctrl_t
struct ctrl_t
{
union
{
@ -290,7 +290,7 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection
struct alignas(128) CellSyncLFQueue
{
struct alignas(8) pop1_t
struct pop1_t
{
be_t<u16> m_h1;
be_t<u16> m_h2;
@ -303,13 +303,13 @@ struct alignas(128) CellSyncLFQueue
be_t<u16> pack;
};
struct alignas(4) pop3_t
struct pop3_t
{
be_t<u16> m_h1;
be_t<u16> m_h2;
};
struct alignas(8) push1_t
struct push1_t
{
be_t<u16> m_h5;
be_t<u16> m_h6;
@ -322,7 +322,7 @@ struct alignas(128) CellSyncLFQueue
be_t<u16> pack;
};
struct alignas(4) push3_t
struct push3_t
{
be_t<u16> m_h5;
be_t<u16> m_h6;

View File

@ -254,10 +254,10 @@ void atomic_wait::list<Max, T...>::wait(atomic_wait_timeout timeout)
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");
/* First part: Non-MSVC intrinsics */
using type = get_uint_t<sizeof(T)>;
#ifndef _MSC_VER
#if defined(__ATOMIC_HLE_ACQUIRE) && defined(__ATOMIC_HLE_RELEASE)
@ -270,19 +270,19 @@ struct atomic_storage
static inline bool compare_exchange(T& dest, T& comp, T exch)
{
return __atomic_compare_exchange(&dest, &comp, &exch, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return __atomic_compare_exchange(reinterpret_cast<type*>(&dest), reinterpret_cast<type*>(&comp), reinterpret_cast<type*>(&exch), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
}
static inline bool compare_exchange_hle_acq(T& dest, T& comp, T exch)
{
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
return __atomic_compare_exchange(&dest, &comp, &exch, false, s_hle_ack, s_hle_ack);
return __atomic_compare_exchange(reinterpret_cast<type*>(&dest), reinterpret_cast<type*>(&comp), reinterpret_cast<type*>(&exch), false, s_hle_ack, s_hle_ack);
}
static inline T load(const T& dest)
{
T result;
__atomic_load(&dest, &result, __ATOMIC_SEQ_CST);
__atomic_load(reinterpret_cast<const type*>(&dest), reinterpret_cast<type*>(&result), __ATOMIC_SEQ_CST);
return result;
}
@ -293,13 +293,13 @@ struct atomic_storage
static inline void release(T& dest, T value)
{
__atomic_store(&dest, &value, __ATOMIC_RELEASE);
__atomic_store(reinterpret_cast<type*>(&dest), reinterpret_cast<type*>(&value), __ATOMIC_RELEASE);
}
static inline T exchange(T& dest, T value)
{
T result;
__atomic_exchange(&dest, &value, &result, __ATOMIC_SEQ_CST);
__atomic_exchange(reinterpret_cast<type*>(&dest), reinterpret_cast<type*>(&value), reinterpret_cast<type*>(&result), __ATOMIC_SEQ_CST);
return result;
}
@ -909,6 +909,7 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
static inline T exchange(T& dest, T value)
{
__atomic_thread_fence(__ATOMIC_ACQ_REL);
return std::bit_cast<T>(__sync_lock_test_and_set(reinterpret_cast<u128*>(&dest), std::bit_cast<u128>(value)));
}
@ -929,7 +930,7 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
};
// Atomic type with lock-free and standard layout guarantees (and appropriate limitations)
template <typename T, std::size_t Align = alignof(T)>
template <typename T, std::size_t Align = sizeof(T)>
class atomic_t
{
protected:
@ -937,11 +938,22 @@ protected:
using ptr_rt = std::conditional_t<std::is_pointer_v<type>, ullong, type>;
static_assert(alignof(type) == sizeof(type), "atomic_t<> error: unexpected alignment, use alignas() if necessary");
static_assert((Align & (Align - 1)) == 0, "atomic_t<> error: unexpected Align parameter (not power of 2).");
static_assert(Align % sizeof(type) == 0, "atomic_t<> error: invalid type, must be power of 2.");
static_assert(sizeof(type) <= 16, "atomic_t<> error: invalid type, too big (max supported size is 16).");
static_assert(Align >= sizeof(type), "atomic_t<> error: bad args, specify bigger alignment if necessary.");
static_assert(std::is_trivially_copyable_v<type>);
static_assert(std::is_copy_constructible_v<type>);
static_assert(std::is_move_constructible_v<type>);
static_assert(std::is_copy_assignable_v<type>);
static_assert(std::is_move_assignable_v<type>);
alignas(Align) type m_data;
public:
static constexpr std::size_t align = Align;
atomic_t() noexcept = default;
atomic_t(const atomic_t&) = delete;