mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03: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:
parent
8efc22bd45
commit
d1e7837422
6 changed files with 38 additions and 20 deletions
|
@ -539,6 +539,12 @@ struct alignas(16) s128
|
||||||
CHECK_SIZE_ALIGN(u128, 16, 16);
|
CHECK_SIZE_ALIGN(u128, 16, 16);
|
||||||
CHECK_SIZE_ALIGN(s128, 16, 16);
|
CHECK_SIZE_ALIGN(s128, 16, 16);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct get_int_impl<16>
|
||||||
|
{
|
||||||
|
using utype = u128;
|
||||||
|
};
|
||||||
|
|
||||||
// Return magic value for any unsigned type
|
// Return magic value for any unsigned type
|
||||||
constexpr inline struct umax_helper
|
constexpr inline struct umax_helper
|
||||||
{
|
{
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct audio_port
|
||||||
u32 size;
|
u32 size;
|
||||||
u64 timestamp; // copy of global timestamp
|
u64 timestamp; // copy of global timestamp
|
||||||
|
|
||||||
struct alignas(8) level_set_t
|
struct level_set_t
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
float inc;
|
float inc;
|
||||||
|
|
|
@ -410,7 +410,7 @@ bool squeue_test_exit();
|
||||||
template<typename T, u32 sq_size = 256>
|
template<typename T, u32 sq_size = 256>
|
||||||
class squeue_t
|
class squeue_t
|
||||||
{
|
{
|
||||||
struct alignas(8) squeue_sync_var_t
|
struct squeue_sync_var_t
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -692,7 +692,7 @@ struct alignas(128) CellSpurs
|
||||||
u8 xCA; // 0xCA
|
u8 xCA; // 0xCA
|
||||||
u8 xCB; // 0xCB
|
u8 xCB; // 0xCB
|
||||||
|
|
||||||
struct alignas(4) SrvTraceSyncVar
|
struct SrvTraceSyncVar
|
||||||
{
|
{
|
||||||
u8 sysSrvTraceInitialised; // 0xCC
|
u8 sysSrvTraceInitialised; // 0xCC
|
||||||
u8 sysSrvNotifyUpdateTraceComplete; // 0xCD
|
u8 sysSrvNotifyUpdateTraceComplete; // 0xCD
|
||||||
|
@ -881,7 +881,7 @@ CHECK_SIZE_ALIGN(CellSpursWorkloadAttribute, 512, 8);
|
||||||
|
|
||||||
struct alignas(128) CellSpursEventFlag
|
struct alignas(128) CellSpursEventFlag
|
||||||
{
|
{
|
||||||
struct alignas(8) ControlSyncVar
|
struct ControlSyncVar
|
||||||
{
|
{
|
||||||
be_t<u16> events; // 0x00 Event bits
|
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
|
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
|
||||||
|
|
|
@ -36,7 +36,7 @@ enum CellSyncError1 : u32
|
||||||
|
|
||||||
struct CellSyncMutex
|
struct CellSyncMutex
|
||||||
{
|
{
|
||||||
struct alignas(4) Counter
|
struct Counter
|
||||||
{
|
{
|
||||||
be_t<u16> rel;
|
be_t<u16> rel;
|
||||||
be_t<u16> acq;
|
be_t<u16> acq;
|
||||||
|
@ -162,7 +162,7 @@ CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16);
|
||||||
|
|
||||||
struct alignas(32) CellSyncQueue
|
struct alignas(32) CellSyncQueue
|
||||||
{
|
{
|
||||||
struct alignas(8) ctrl_t
|
struct ctrl_t
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -290,7 +290,7 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection
|
||||||
|
|
||||||
struct alignas(128) CellSyncLFQueue
|
struct alignas(128) CellSyncLFQueue
|
||||||
{
|
{
|
||||||
struct alignas(8) pop1_t
|
struct pop1_t
|
||||||
{
|
{
|
||||||
be_t<u16> m_h1;
|
be_t<u16> m_h1;
|
||||||
be_t<u16> m_h2;
|
be_t<u16> m_h2;
|
||||||
|
@ -303,13 +303,13 @@ struct alignas(128) CellSyncLFQueue
|
||||||
be_t<u16> pack;
|
be_t<u16> pack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(4) pop3_t
|
struct pop3_t
|
||||||
{
|
{
|
||||||
be_t<u16> m_h1;
|
be_t<u16> m_h1;
|
||||||
be_t<u16> m_h2;
|
be_t<u16> m_h2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(8) push1_t
|
struct push1_t
|
||||||
{
|
{
|
||||||
be_t<u16> m_h5;
|
be_t<u16> m_h5;
|
||||||
be_t<u16> m_h6;
|
be_t<u16> m_h6;
|
||||||
|
@ -322,7 +322,7 @@ struct alignas(128) CellSyncLFQueue
|
||||||
be_t<u16> pack;
|
be_t<u16> pack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(4) push3_t
|
struct push3_t
|
||||||
{
|
{
|
||||||
be_t<u16> m_h5;
|
be_t<u16> m_h5;
|
||||||
be_t<u16> m_h6;
|
be_t<u16> m_h6;
|
||||||
|
|
|
@ -254,10 +254,10 @@ void atomic_wait::list<Max, T...>::wait(atomic_wait_timeout timeout)
|
||||||
template <typename T, std::size_t Size = sizeof(T)>
|
template <typename T, std::size_t Size = sizeof(T)>
|
||||||
struct atomic_storage
|
struct atomic_storage
|
||||||
{
|
{
|
||||||
static_assert(sizeof(T) <= 16 && sizeof(T) == alignof(T), "atomic_storage<> error: invalid type");
|
|
||||||
|
|
||||||
/* First part: Non-MSVC intrinsics */
|
/* First part: Non-MSVC intrinsics */
|
||||||
|
|
||||||
|
using type = get_uint_t<sizeof(T)>;
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
|
||||||
#if defined(__ATOMIC_HLE_ACQUIRE) && defined(__ATOMIC_HLE_RELEASE)
|
#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)
|
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 inline bool compare_exchange_hle_acq(T& dest, T& comp, T exch)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
|
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)
|
static inline T load(const T& dest)
|
||||||
{
|
{
|
||||||
T result;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,13 +293,13 @@ struct atomic_storage
|
||||||
|
|
||||||
static inline void release(T& dest, T value)
|
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)
|
static inline T exchange(T& dest, T value)
|
||||||
{
|
{
|
||||||
T result;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,6 +909,7 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
||||||
|
|
||||||
static inline T exchange(T& dest, T value)
|
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)));
|
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)
|
// 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
|
class atomic_t
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -937,11 +938,22 @@ protected:
|
||||||
|
|
||||||
using ptr_rt = std::conditional_t<std::is_pointer_v<type>, ullong, type>;
|
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;
|
alignas(Align) type m_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr std::size_t align = Align;
|
||||||
|
|
||||||
atomic_t() noexcept = default;
|
atomic_t() noexcept = default;
|
||||||
|
|
||||||
atomic_t(const atomic_t&) = delete;
|
atomic_t(const atomic_t&) = delete;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue