atomic_op() rewritten, atomic.h refactoring

cellSync refactoring, wait_op() rewritten, bugfixes
This commit is contained in:
Nekotekina 2015-06-26 02:26:23 +03:00
parent 39f836b495
commit c598fe7aa9
24 changed files with 725 additions and 754 deletions

View file

@ -165,13 +165,6 @@ union u128
} _bit; } _bit;
//operator u64() const { return _u64[0]; }
//operator u32() const { return _u32[0]; }
//operator u16() const { return _u16[0]; }
//operator u8() const { return _u8[0]; }
//operator bool() const { return _u64[0] != 0 || _u64[1] != 0; }
static u128 from64(u64 _0, u64 _1 = 0) static u128 from64(u64 _0, u64 _1 = 0)
{ {
u128 ret; u128 ret;
@ -443,7 +436,7 @@ static force_inline u128 sync_fetch_and_xor(volatile u128* dest, u128 value)
} }
} }
template<typename T, int size = sizeof(T)> struct se_t; template<typename T, std::size_t Size = sizeof(T)> struct se_t;
template<typename T> struct se_t<T, 2> template<typename T> struct se_t<T, 2>
{ {
@ -501,16 +494,13 @@ template<typename T> struct se_t<T, 16>
} }
}; };
template<typename T, T _value, size_t size = sizeof(T)> struct const_se_t; template<typename T, T _value, std::size_t size = sizeof(T)> struct const_se_t;
template<u8 _value> struct const_se_t<u8, _value, 1>
{
static const u8 value = _value;
};
template<u16 _value> struct const_se_t<u16, _value, 2> template<u16 _value> struct const_se_t<u16, _value, 2>
{ {
static const u16 value = ((_value >> 8) & 0xff) | ((_value << 8) & 0xff00); static const u16 value =
((_value >> 8) & 0x00ff) |
((_value << 8) & 0xff00);
}; };
template<u32 _value> struct const_se_t<u32, _value, 4> template<u32 _value> struct const_se_t<u32, _value, 4>
@ -600,9 +590,9 @@ public:
using stype = be_storage_t<std::remove_cv_t<T>>; using stype = be_storage_t<std::remove_cv_t<T>>;
#ifdef IS_LE_MACHINE #ifdef IS_LE_MACHINE
stype m_data; stype m_data; // don't access directly
#else #else
type m_data; type m_data; // don't access directly
#endif #endif
static_assert(!std::is_class<type>::value, "be_t<> error: invalid type (class or structure)"); static_assert(!std::is_class<type>::value, "be_t<> error: invalid type (class or structure)");
@ -695,41 +685,41 @@ public:
be_t& operator --() { *this -= 1; return *this; } be_t& operator --() { *this -= 1; return *this; }
}; };
template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value, bool> operator ==(const be_t<T1>& left, const be_t<T2>& right) template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value && std::is_integral<T1>::value, bool> operator ==(const be_t<T1>& left, const be_t<T2>& right)
{ {
return left.data() == right.data(); return left.data() == right.data();
} }
template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value, bool> operator !=(const be_t<T1>& left, const be_t<T2>& right) template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value && std::is_integral<T1>::value, bool> operator !=(const be_t<T1>& left, const be_t<T2>& right)
{ {
return left.data() != right.data(); return left.data() != right.data();
} }
template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value, be_t<T1>> operator &(const be_t<T1>& left, const be_t<T2>& right) template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value && std::is_integral<T1>::value, be_t<T1>> operator &(const be_t<T1>& left, const be_t<T2>& right)
{ {
be_t<T1> result; be_t<T1> result;
result.m_data = left.data() & right.data(); result.m_data = left.data() & right.data();
return result; return result;
} }
template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value, be_t<T1>> operator |(const be_t<T1>& left, const be_t<T2>& right) template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value && std::is_integral<T1>::value, be_t<T1>> operator |(const be_t<T1>& left, const be_t<T2>& right)
{ {
be_t<T1> result; be_t<T1> result;
result.m_data = left.data() | right.data(); result.m_data = left.data() | right.data();
return result; return result;
} }
template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value, be_t<T1>> operator ^(const be_t<T1>& left, const be_t<T2>& right) template<typename T1, typename T2> inline std::enable_if_t<std::is_same<T1, T2>::value && std::is_integral<T1>::value, be_t<T1>> operator ^(const be_t<T1>& left, const be_t<T2>& right)
{ {
be_t<T1> result; be_t<T1> result;
result.m_data = left.data() ^ right.data(); result.m_data = left.data() ^ right.data();
return result; return result;
} }
template<typename T1> inline std::enable_if_t<true, be_t<T1>> operator ~(const be_t<T1>& other) template<typename T1> inline std::enable_if_t<std::is_integral<T1>::value, be_t<T1>> operator ~(const be_t<T1>& arg)
{ {
be_t<T1> result; be_t<T1> result;
result.m_data = ~other.data(); result.m_data = ~arg.data();
return result; return result;
} }
@ -782,7 +772,7 @@ public:
using type = std::remove_cv_t<T>; using type = std::remove_cv_t<T>;
using stype = be_storage_t<std::remove_cv_t<T>>; using stype = be_storage_t<std::remove_cv_t<T>>;
type m_data; type m_data; // don't access directly
static_assert(!std::is_class<type>::value, "le_t<> error: invalid type (class or structure)"); static_assert(!std::is_class<type>::value, "le_t<> error: invalid type (class or structure)");
static_assert(!std::is_union<type>::value || std::is_same<type, u128>::value, "le_t<> error: invalid type (union)"); static_assert(!std::is_union<type>::value || std::is_same<type, u128>::value, "le_t<> error: invalid type (union)");

View file

@ -749,7 +749,7 @@ size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, siz
if (op == X64OP_CMPXCHG) if (op == X64OP_CMPXCHG)
{ {
// detect whether this instruction can't actually modify memory to avoid breaking reservation; // detect whether this instruction can't actually modify memory to avoid breaking reservation;
// this may theoretically cause endless loop, but it shouldn't be a problem if only read_sync() generates such instruction // this may theoretically cause endless loop, but it shouldn't be a problem if only load_sync() generates such instruction
u64 cmp, exch; u64 cmp, exch;
if (!get_x64_reg_value(context, reg, d_size, i_size, cmp) || !get_x64_reg_value(context, X64R_RAX, d_size, i_size, exch)) if (!get_x64_reg_value(context, reg, d_size, i_size, cmp) || !get_x64_reg_value(context, X64R_RAX, d_size, i_size, exch))
{ {
@ -1480,16 +1480,22 @@ bool thread_t::joinable() const
return m_state == TS_JOINABLE; return m_state == TS_JOINABLE;
} }
bool waiter_map_t::is_stopped(u64 signal_id) bool waiter_map_t::is_stopped(u32 addr)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
LOG_WARNING(Log::HLE, "%s: waiter_op() aborted (signal_id=0x%llx)", name.c_str(), signal_id); LOG_WARNING(Log::HLE, "%s: waiter_op() aborted (addr=0x%x)", name.c_str(), addr);
return true; return true;
} }
return false; return false;
} }
void waiter_map_t::notify(u32 addr)
{
// signal appropriate condition variable
cv[get_hash(addr)].notify_all();
}
const std::function<bool()> SQUEUE_ALWAYS_EXIT = [](){ return true; }; const std::function<bool()> SQUEUE_ALWAYS_EXIT = [](){ return true; };
const std::function<bool()> SQUEUE_NEVER_EXIT = [](){ return false; }; const std::function<bool()> SQUEUE_NEVER_EXIT = [](){ return false; };

View file

@ -103,7 +103,7 @@ class slw_shared_mutex_t
struct waiter_map_t struct waiter_map_t
{ {
static const size_t size = 32; static const size_t size = 16;
std::array<std::mutex, size> mutex; std::array<std::mutex, size> mutex;
std::array<std::condition_variable, size> cv; std::array<std::condition_variable, size> cv;
@ -115,40 +115,43 @@ struct waiter_map_t
{ {
} }
bool is_stopped(u64 signal_id); // generate simple "hash" for mutex/cv distribution
u32 get_hash(u32 addr)
{
addr ^= addr >> 16;
addr ^= addr >> 24;
addr ^= addr >> 28;
return addr % size;
}
// check emu status
bool is_stopped(u32 addr);
// wait until waiter_func() returns true, signal_id is an arbitrary number // wait until waiter_func() returns true, signal_id is an arbitrary number
template<typename S, typename WT> force_inline safe_buffers void wait_op(const S& signal_id, const WT waiter_func) template<typename F, typename... Args> safe_buffers auto wait_op(u32 addr, F pred, Args&&... args) -> decltype(static_cast<void>(pred(args...)))
{ {
// generate hash const u32 hash = get_hash(addr);
const auto hash = std::hash<S>()(signal_id) % size;
// set mutex locker // set mutex locker
std::unique_lock<std::mutex> locker(mutex[hash], std::defer_lock); std::unique_lock<std::mutex> lock(mutex[hash], std::defer_lock);
// check the condition or if the emulator is stopped while (true)
while (!waiter_func() && !is_stopped(signal_id))
{ {
// check the condition
if (pred(args...)) return;
// lock the mutex and initialize waiter (only once) // lock the mutex and initialize waiter (only once)
if (!locker.owns_lock()) if (!lock) lock.lock();
{
locker.lock();
}
// wait on appropriate condition variable for 1 ms or until signal arrived // wait on appropriate condition variable for 1 ms or until signal arrived
cv[hash].wait_for(locker, std::chrono::milliseconds(1)); cv[hash].wait_for(lock, std::chrono::milliseconds(1));
if (is_stopped(addr)) return;
} }
} }
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met) // signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
template<typename S> force_inline void notify(const S& signal_id) void notify(u32 addr);
{
// generate hash
const auto hash = std::hash<S>()(signal_id) % size;
// signal appropriate condition variable
cv[hash].notify_all();
}
}; };
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT; extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
@ -209,7 +212,7 @@ public:
{ {
u32 pos = 0; u32 pos = 0;
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos](squeue_sync_var_t& sync) -> u32 while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{ {
assert(sync.count <= sq_size); assert(sync.count <= sq_size);
assert(sync.position < sq_size); assert(sync.position < sq_size);
@ -272,7 +275,7 @@ public:
{ {
u32 pos = 0; u32 pos = 0;
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos](squeue_sync_var_t& sync) -> u32 while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{ {
assert(sync.count <= sq_size); assert(sync.count <= sq_size);
assert(sync.position < sq_size); assert(sync.position < sq_size);
@ -341,7 +344,7 @@ public:
assert(start_pos < sq_size); assert(start_pos < sq_size);
u32 pos = 0; u32 pos = 0;
while (u32 res = m_sync.atomic_op_sync(SQSVR_OK, [&pos, start_pos](squeue_sync_var_t& sync) -> u32 while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
{ {
assert(sync.count <= sq_size); assert(sync.count <= sq_size);
assert(sync.position < sq_size); assert(sync.position < sq_size);
@ -425,7 +428,7 @@ public:
{ {
u32 pos, count; u32 pos, count;
while (m_sync.atomic_op_sync(SQSVR_OK, [&pos, &count](squeue_sync_var_t& sync) -> u32 while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
{ {
assert(sync.count <= sq_size); assert(sync.count <= sq_size);
assert(sync.position < sq_size); assert(sync.position < sq_size);
@ -463,7 +466,7 @@ public:
void clear() void clear()
{ {
while (m_sync.atomic_op_sync(SQSVR_OK, [](squeue_sync_var_t& sync) -> u32 while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
{ {
assert(sync.count <= sq_size); assert(sync.count <= sq_size);
assert(sync.position < sq_size); assert(sync.position < sq_size);

View file

@ -76,7 +76,7 @@ bool RawSPUThread::ReadReg(const u32 addr, u32& value)
case SPU_Status_offs: case SPU_Status_offs:
{ {
value = status.read_relaxed(); value = status.load();
return true; return true;
} }
} }
@ -185,7 +185,7 @@ bool RawSPUThread::WriteReg(const u32 addr, const u32 value)
break; break;
} }
run_ctrl.write_relaxed(value); run_ctrl.store(value);
return true; return true;
} }
@ -196,7 +196,7 @@ bool RawSPUThread::WriteReg(const u32 addr, const u32 value)
break; break;
} }
npc.write_relaxed(value); npc.store(value);
return true; return true;
} }
@ -223,5 +223,5 @@ void RawSPUThread::Task()
SPUThread::Task(); SPUThread::Task();
npc.write_relaxed(PC | 1); npc.store(PC | 1);
} }

View file

@ -495,7 +495,7 @@ u32 SPUThread::get_ch_count(u32 ch)
case SPU_RdSigNotify1: return ch_snr1.get_count(); break; case SPU_RdSigNotify1: return ch_snr1.get_count(); break;
case SPU_RdSigNotify2: return ch_snr2.get_count(); break; case SPU_RdSigNotify2: return ch_snr2.get_count(); break;
case MFC_RdAtomicStat: return ch_atomic_stat.get_count(); break; case MFC_RdAtomicStat: return ch_atomic_stat.get_count(); break;
case SPU_RdEventStat: return ch_event_stat.read_relaxed() & ch_event_mask ? 1 : 0; break; case SPU_RdEventStat: return ch_event_stat.load() & ch_event_mask ? 1 : 0; break;
} }
LOG_ERROR(SPU, "get_ch_count(ch=%d [%s]): unknown/illegal channel", ch, ch < 128 ? spu_ch_name[ch] : "???"); LOG_ERROR(SPU, "get_ch_count(ch=%d [%s]): unknown/illegal channel", ch, ch < 128 ? spu_ch_name[ch] : "???");
@ -603,7 +603,7 @@ u32 SPUThread::get_ch_value(u32 ch)
case SPU_RdEventStat: case SPU_RdEventStat:
{ {
u32 result; u32 result;
while (!(result = ch_event_stat.read_relaxed() & ch_event_mask) && !Emu.IsStopped()) while (!(result = ch_event_stat.load() & ch_event_mask) && !Emu.IsStopped())
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }

View file

@ -199,7 +199,7 @@ public:
void set_value(u32 value, u32 count = 1) void set_value(u32 value, u32 count = 1)
{ {
sync_var.write_relaxed({ count, value }); sync_var.store({ count, value });
} }
u32 get_value() volatile u32 get_value() volatile
@ -254,7 +254,7 @@ public:
{ {
bool out_result; bool out_result;
const u32 last_value = value3.read_sync(); const u32 last_value = value3.load_sync();
sync_var.atomic_op([&out_result, &out_value, &out_count, last_value](sync_var_t& data) sync_var.atomic_op([&out_result, &out_value, &out_count, last_value](sync_var_t& data)
{ {
@ -292,7 +292,7 @@ public:
void set(u64 ints) void set(u64 ints)
{ {
// leave only enabled interrupts // leave only enabled interrupts
ints &= mask.read_relaxed(); ints &= mask.load();
if (ints && ~stat._or(ints) & ints) if (ints && ~stat._or(ints) & ints)
{ {

View file

@ -32,6 +32,43 @@ template<typename T> struct _to_atomic_subtype<T, 16>
template<typename T> using atomic_subtype_t = typename _to_atomic_subtype<T>::type; template<typename T> using atomic_subtype_t = typename _to_atomic_subtype<T>::type;
// result wrapper to deal with void result type
template<typename RT> struct atomic_op_result_t
{
RT result;
template<typename T, typename... Args> inline atomic_op_result_t(T func, Args&&... args)
: result(std::move(func(std::forward<Args>(args)...)))
{
}
inline RT move()
{
return std::move(result);
}
};
// void specialization
template<> struct atomic_op_result_t<void>
{
template<typename T, typename... Args> inline atomic_op_result_t(T func, Args&&... args)
{
func(std::forward<Args>(args)...);
}
inline void move()
{
}
};
struct break_never_t
{
template<typename RT> inline bool operator()(const atomic_op_result_t<RT>&) const
{
return false;
}
};
template<typename T> union _atomic_base template<typename T> union _atomic_base
{ {
using type = std::remove_cv_t<T>; using type = std::remove_cv_t<T>;
@ -55,6 +92,27 @@ template<typename T> union _atomic_base
return reinterpret_cast<type&>(value); return reinterpret_cast<type&>(value);
} }
private:
template<typename T2> force_inline static void write_relaxed(volatile T2& data, const T2& value)
{
data = value;
}
force_inline static void write_relaxed(volatile u128& data, const u128& value)
{
sync_lock_test_and_set(&data, value);
}
template<typename T2> force_inline static T2 read_relaxed(const volatile T2& data)
{
return data;
}
force_inline static u128 read_relaxed(const volatile u128& value)
{
return sync_val_compare_and_swap(const_cast<volatile u128*>(&value), {}, {});
}
public: public:
// atomically compare data with cmp, replace with exch if equal, return previous data value anyway // atomically compare data with cmp, replace with exch if equal, return previous data value anyway
force_inline const type compare_and_swap(const type& cmp, const type& exch) volatile force_inline const type compare_and_swap(const type& cmp, const type& exch) volatile
@ -69,7 +127,7 @@ public:
} }
// read data with memory barrier // read data with memory barrier
force_inline const type read_sync() const volatile force_inline const type load_sync() const volatile
{ {
const subtype zero = {}; const subtype zero = {};
return from_subtype(sync_val_compare_and_swap(const_cast<subtype*>(&sub_data), zero, zero)); return from_subtype(sync_val_compare_and_swap(const_cast<subtype*>(&sub_data), zero, zero));
@ -81,73 +139,42 @@ public:
return from_subtype(sync_lock_test_and_set(&sub_data, to_subtype(exch))); return from_subtype(sync_lock_test_and_set(&sub_data, to_subtype(exch)));
} }
// read data without memory barrier // read data without memory barrier (works as load_sync() for 128 bit)
force_inline const type read_relaxed() const volatile force_inline const type load() const volatile
{ {
const subtype value = const_cast<const subtype&>(sub_data); return from_subtype(read_relaxed(sub_data));
return from_subtype(value);
} }
// write data without memory barrier // write data without memory barrier (works as exchange() for 128 bit, discarding result)
force_inline void write_relaxed(const type& value) volatile force_inline void store(const type& value) volatile
{ {
const_cast<subtype&>(sub_data) = to_subtype(value); write_relaxed(sub_data, to_subtype(value));
} }
// perform atomic operation on data // perform an atomic operation on data (callable object version, first arg is a reference to atomic type)
template<typename FT> force_inline void atomic_op(const FT atomic_proc) volatile template<typename Break_if = break_never_t, typename F, typename... Args> auto atomic_op(F func, Args&&... args) volatile -> decltype(func(std::declval<T&>(), args...))
{ {
while (true) while (true)
{ {
const subtype old = const_cast<const subtype&>(sub_data); // read the old value from memory
const subtype old = read_relaxed(sub_data);
// copy the old value
subtype _new = old; subtype _new = old;
atomic_proc(to_type(_new)); // function should accept reference to T type
if (sync_bool_compare_and_swap(&sub_data, old, _new)) return; // call atomic op for the local copy of the old value and save the return value of the function
atomic_op_result_t<std::result_of_t<F(T&, Args...)>> result(func, to_type(_new), args...);
// 1) check return value using callable object of Break_if type, return if condition met
// 2) atomically compare value with `old`, replace with `_new` and return on success
if (Break_if()(result) || sync_bool_compare_and_swap(&sub_data, old, _new)) return result.move();
} }
} }
// perform atomic operation on data with special exit condition (if intermediate result != proceed_value) // perform an atomic operation on data (member function version)
template<typename RT, typename FT> force_inline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile template<typename Break_if = break_never_t, typename CT, typename RT, typename... FArgs, typename... Args, typename = std::enable_if_t<std::is_same<T, CT>::value>> auto atomic_op(RT(CT::* func)(FArgs...), Args&&... args) volatile -> decltype((std::declval<T&>().*func)(args...))
{ {
while (true) return atomic_op<Break_if>(std::mem_fn(func), std::forward<Args>(args)...);
{
const subtype old = const_cast<const subtype&>(sub_data);
subtype _new = old;
auto res = static_cast<RT>(atomic_proc(to_type(_new))); // function should accept reference to T type and return some value
if (res != proceed_value) return res;
if (sync_bool_compare_and_swap(&sub_data, old, _new)) return proceed_value;
}
}
// perform atomic operation on data with additional memory barrier
template<typename FT> force_inline void atomic_op_sync(const FT atomic_proc) volatile
{
const subtype zero = {};
subtype old = sync_val_compare_and_swap(&sub_data, zero, zero);
while (true)
{
subtype _new = old;
atomic_proc(to_type(_new)); // function should accept reference to T type
const subtype val = sync_val_compare_and_swap(&sub_data, old, _new);
if (val == old) return;
old = val;
}
}
// perform atomic operation on data with additional memory barrier and special exit condition (if intermediate result != proceed_value)
template<typename RT, typename FT> force_inline RT atomic_op_sync(const RT proceed_value, const FT atomic_proc) volatile
{
const subtype zero = {};
subtype old = sync_val_compare_and_swap(&sub_data, zero, zero);
while (true)
{
subtype _new = old;
auto res = static_cast<RT>(atomic_proc(to_type(_new))); // function should accept reference to T type and return some value
if (res != proceed_value) return res;
const subtype val = sync_val_compare_and_swap(&sub_data, old, _new);
if (val == old) return proceed_value;
old = val;
}
} }
// atomic bitwise OR, returns previous data // atomic bitwise OR, returns previous data
@ -174,17 +201,17 @@ public:
return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right))); return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)));
} }
force_inline const type operator |= (const type& right) volatile force_inline const type operator |=(const type& right) volatile
{ {
return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right)) | to_subtype(right)); return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right)) | to_subtype(right));
} }
force_inline const type operator &= (const type& right) volatile force_inline const type operator &=(const type& right) volatile
{ {
return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right)) & to_subtype(right)); return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right)) & to_subtype(right));
} }
force_inline const type operator ^= (const type& right) volatile force_inline const type operator ^=(const type& right) volatile
{ {
return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)) ^ to_subtype(right)); return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)) ^ to_subtype(right));
} }
@ -225,74 +252,50 @@ template<typename T, typename T2> inline if_integral_le_t<T, T2> operator -=(_at
template<typename T> inline if_integral_be_t<T> operator ++(_atomic_base<be_t<T>>& left) template<typename T> inline if_integral_be_t<T> operator ++(_atomic_base<be_t<T>>& left)
{ {
be_t<T> result; return left.atomic_op([](be_t<T>& value) -> be_t<T>
left.atomic_op([&result](be_t<T>& value)
{ {
result = ++value; return ++value;
}); });
return result;
} }
template<typename T> inline if_integral_be_t<T> operator --(_atomic_base<be_t<T>>& left) template<typename T> inline if_integral_be_t<T> operator --(_atomic_base<be_t<T>>& left)
{ {
be_t<T> result; return left.atomic_op([](be_t<T>& value) -> be_t<T>
left.atomic_op([&result](be_t<T>& value)
{ {
result = --value; return --value;
}); });
return result;
} }
template<typename T> inline if_integral_be_t<T> operator ++(_atomic_base<be_t<T>>& left, int) template<typename T> inline if_integral_be_t<T> operator ++(_atomic_base<be_t<T>>& left, int)
{ {
be_t<T> result; return left.atomic_op([](be_t<T>& value) -> be_t<T>
left.atomic_op([&result](be_t<T>& value)
{ {
result = value++; return value++;
}); });
return result;
} }
template<typename T> inline if_integral_be_t<T> operator --(_atomic_base<be_t<T>>& left, int) template<typename T> inline if_integral_be_t<T> operator --(_atomic_base<be_t<T>>& left, int)
{ {
be_t<T> result; return left.atomic_op([](be_t<T>& value) -> be_t<T>
left.atomic_op([&result](be_t<T>& value)
{ {
result = value--; return value--;
}); });
return result;
} }
template<typename T, typename T2> inline if_integral_be_t<T, T2> operator +=(_atomic_base<be_t<T>>& left, T2 right) template<typename T, typename T2> inline if_integral_be_t<T, T2> operator +=(_atomic_base<be_t<T>>& left, T2 right)
{ {
be_t<T> result; return left.atomic_op([right](be_t<T>& value) -> be_t<T>
left.atomic_op([&result, right](be_t<T>& value)
{ {
result = (value += right); return value += right;
}); });
return result;
} }
template<typename T, typename T2> inline if_integral_be_t<T, T2> operator -=(_atomic_base<be_t<T>>& left, T2 right) template<typename T, typename T2> inline if_integral_be_t<T, T2> operator -=(_atomic_base<be_t<T>>& left, T2 right)
{ {
be_t<T> result; return left.atomic_op([right](be_t<T>& value) -> be_t<T>
left.atomic_op([&result, right](be_t<T>& value)
{ {
result = (value -= right); return value -= right;
}); });
return result;
} }
template<typename T> using atomic = _atomic_base<T>; // Atomic Type with native endianness (for emulator memory) template<typename T> using atomic = _atomic_base<T>; // Atomic Type with native endianness (for emulator memory)

View file

@ -208,7 +208,7 @@ namespace vm
{ {
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex); std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
u8 flags = g_page_info[addr >> 12].read_relaxed(); u8 flags = g_page_info[addr >> 12].load();
if (!(flags & page_writable) || !(flags & page_allocated) || (flags & page_no_reservations)) if (!(flags & page_writable) || !(flags & page_allocated) || (flags & page_no_reservations))
{ {
throw fmt::format("vm::reservation_acquire(addr=0x%x, size=0x%x) failed (invalid page flags: 0x%x)", addr, size, flags); throw fmt::format("vm::reservation_acquire(addr=0x%x, size=0x%x) failed (invalid page flags: 0x%x)", addr, size, flags);
@ -355,7 +355,7 @@ namespace vm
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
{ {
if (g_page_info[i].read_relaxed()) if (g_page_info[i].load())
{ {
throw fmt::format("vm::page_map(addr=0x%x, size=0x%x, flags=0x%x) failed (already mapped at 0x%x)", addr, size, flags, i * 4096); throw fmt::format("vm::page_map(addr=0x%x, size=0x%x, flags=0x%x) failed (already mapped at 0x%x)", addr, size, flags, i * 4096);
} }
@ -398,7 +398,7 @@ namespace vm
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
{ {
if ((g_page_info[i].read_relaxed() & flags_test) != (flags_test | page_allocated)) if ((g_page_info[i].load() & flags_test) != (flags_test | page_allocated))
{ {
return false; return false;
} }
@ -447,7 +447,7 @@ namespace vm
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
{ {
if (!(g_page_info[i].read_relaxed() & page_allocated)) if (!(g_page_info[i].load() & page_allocated))
{ {
throw fmt::format("vm::page_unmap(addr=0x%x, size=0x%x) failed (not mapped at 0x%x)", addr, size, i * 4096); throw fmt::format("vm::page_unmap(addr=0x%x, size=0x%x) failed (not mapped at 0x%x)", addr, size, i * 4096);
} }
@ -491,7 +491,7 @@ namespace vm
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
{ {
if ((g_page_info[i].read_sync() & page_allocated) != page_allocated) if ((g_page_info[i].load() & page_allocated) != page_allocated)
{ {
return false; return false;
} }

View file

@ -5,7 +5,7 @@ namespace vm
template<typename T, typename AT = u32> template<typename T, typename AT = u32>
struct _ref_base struct _ref_base
{ {
AT m_addr; AT m_addr; // don't access directly
static_assert(!std::is_pointer<T>::value, "vm::_ref_base<> error: invalid type (pointer)"); static_assert(!std::is_pointer<T>::value, "vm::_ref_base<> error: invalid type (pointer)");
static_assert(!std::is_reference<T>::value, "vm::_ref_base<> error: invalid type (reference)"); static_assert(!std::is_reference<T>::value, "vm::_ref_base<> error: invalid type (reference)");

View file

@ -2494,8 +2494,8 @@ void RSXThread::Task()
inc = 1; inc = 1;
u32 get = m_ctrl->get.read_sync(); u32 put = m_ctrl->put.load();
u32 put = m_ctrl->put.read_sync(); u32 get = m_ctrl->get.load();
if (put == get || !Emu.IsRunning()) if (put == get || !Emu.IsRunning())
{ {

View file

@ -31,7 +31,7 @@ s32 cellAudioInit()
// clear ports // clear ports
for (auto& port : g_audio.ports) for (auto& port : g_audio.ports)
{ {
port.state.write_relaxed(AUDIO_PORT_STATE_CLOSED); port.state.store(AUDIO_PORT_STATE_CLOSED);
} }
// reset variables // reset variables
@ -82,7 +82,7 @@ s32 cellAudioInit()
bool opened = false; bool opened = false;
float* buffer; float* buffer;
while (out_queue.pop(buffer, [](){ return g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED; })) while (out_queue.pop(buffer, [](){ return g_audio.state.load() != AUDIO_STATE_INITIALIZED; }))
{ {
if (use_u16) if (use_u16)
{ {
@ -146,7 +146,7 @@ s32 cellAudioInit()
} }
}); });
while (g_audio.state.read_relaxed() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped()) while (g_audio.state.load() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
{ {
if (Emu.IsPaused()) if (Emu.IsPaused())
{ {
@ -193,7 +193,7 @@ s32 cellAudioInit()
// mixing: // mixing:
for (auto& port : g_audio.ports) for (auto& port : g_audio.ports)
{ {
if (port.state.read_relaxed() != AUDIO_PORT_STATE_STARTED) continue; if (port.state.load() != AUDIO_PORT_STATE_STARTED) continue;
const u32 block_size = port.channel * AUDIO_SAMPLES; const u32 block_size = port.channel * AUDIO_SAMPLES;
const u32 position = port.tag % port.block; // old value const u32 position = port.tag % port.block; // old value
@ -206,7 +206,7 @@ s32 cellAudioInit()
auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality
{ {
const auto param = port.level_set.read_sync(); const auto param = port.level_set.load();
if (param.inc != 0.0f) if (param.inc != 0.0f)
{ {
@ -357,7 +357,7 @@ s32 cellAudioInit()
memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float)); memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float));
} }
if (!out_queue.push(out_buffer[out_pos].get(), [](){ return g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED; })) if (!out_queue.push(out_buffer[out_pos].get(), [](){ return g_audio.state.load() != AUDIO_STATE_INITIALIZED; }))
{ {
break; break;
} }
@ -375,7 +375,7 @@ s32 cellAudioInit()
{ {
AudioPortConfig& port = g_audio.ports[i]; AudioPortConfig& port = g_audio.ports[i];
if (port.state.read_relaxed() != AUDIO_PORT_STATE_STARTED) continue; if (port.state.load() != AUDIO_PORT_STATE_STARTED) continue;
u32 position = port.tag % port.block; // old value u32 position = port.tag % port.block; // old value
port.counter = g_audio.counter; port.counter = g_audio.counter;
@ -447,7 +447,7 @@ s32 cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
{ {
cellAudio.Warning("cellAudioPortOpen(audioParam=*0x%x, portNum=*0x%x)", audioParam, portNum); cellAudio.Warning("cellAudioPortOpen(audioParam=*0x%x, portNum=*0x%x)", audioParam, portNum);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -551,7 +551,7 @@ s32 cellAudioGetPortConfig(u32 portNum, vm::ptr<CellAudioPortConfig> portConfig)
{ {
cellAudio.Warning("cellAudioGetPortConfig(portNum=%d, portConfig=*0x%x)", portNum, portConfig); cellAudio.Warning("cellAudioGetPortConfig(portNum=%d, portConfig=*0x%x)", portNum, portConfig);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -565,7 +565,7 @@ s32 cellAudioGetPortConfig(u32 portNum, vm::ptr<CellAudioPortConfig> portConfig)
portConfig->readIndexAddr = port.read_index_addr; portConfig->readIndexAddr = port.read_index_addr;
switch (auto state = port.state.read_sync()) switch (auto state = port.state.load())
{ {
case AUDIO_PORT_STATE_CLOSED: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break; case AUDIO_PORT_STATE_CLOSED: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break;
case AUDIO_PORT_STATE_OPENED: portConfig->status = CELL_AUDIO_STATUS_READY; break; case AUDIO_PORT_STATE_OPENED: portConfig->status = CELL_AUDIO_STATUS_READY; break;
@ -584,7 +584,7 @@ s32 cellAudioPortStart(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStart(portNum=%d)", portNum); cellAudio.Warning("cellAudioPortStart(portNum=%d)", portNum);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -607,7 +607,7 @@ s32 cellAudioPortClose(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortClose(portNum=%d)", portNum); cellAudio.Warning("cellAudioPortClose(portNum=%d)", portNum);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -630,7 +630,7 @@ s32 cellAudioPortStop(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStop(portNum=%d)", portNum); cellAudio.Warning("cellAudioPortStop(portNum=%d)", portNum);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -653,7 +653,7 @@ s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
{ {
cellAudio.Log("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x)", portNum, tag, stamp); cellAudio.Log("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x)", portNum, tag, stamp);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -665,7 +665,7 @@ s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
AudioPortConfig& port = g_audio.ports[portNum]; AudioPortConfig& port = g_audio.ports[portNum];
if (port.state.read_relaxed() == AUDIO_PORT_STATE_CLOSED) if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
{ {
return CELL_AUDIO_ERROR_PORT_NOT_OPEN; return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
} }
@ -683,7 +683,7 @@ s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
{ {
cellAudio.Log("cellAudioGetPortBlockTag(portNum=%d, blockNo=0x%llx, tag=*0x%x)", portNum, blockNo, tag); cellAudio.Log("cellAudioGetPortBlockTag(portNum=%d, blockNo=0x%llx, tag=*0x%x)", portNum, blockNo, tag);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -695,7 +695,7 @@ s32 cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
AudioPortConfig& port = g_audio.ports[portNum]; AudioPortConfig& port = g_audio.ports[portNum];
if (port.state.read_relaxed() == AUDIO_PORT_STATE_CLOSED) if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
{ {
return CELL_AUDIO_ERROR_PORT_NOT_OPEN; return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
} }
@ -726,7 +726,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
{ {
cellAudio.Log("cellAudioSetPortLevel(portNum=%d, level=%f)", portNum, level); cellAudio.Log("cellAudioSetPortLevel(portNum=%d, level=%f)", portNum, level);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -738,7 +738,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
AudioPortConfig& port = g_audio.ports[portNum]; AudioPortConfig& port = g_audio.ports[portNum];
if (port.state.read_relaxed() == AUDIO_PORT_STATE_CLOSED) if (port.state.load() == AUDIO_PORT_STATE_CLOSED)
{ {
return CELL_AUDIO_ERROR_PORT_NOT_OPEN; return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
} }
@ -796,7 +796,7 @@ s32 cellAudioSetNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -829,7 +829,7 @@ s32 cellAudioRemoveNotifyEventQueue(u64 key)
{ {
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -862,7 +862,7 @@ s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
{ {
cellAudio.Log("cellAudioAddData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); cellAudio.Log("cellAudioAddData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -895,7 +895,7 @@ s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volu
{ {
cellAudio.Log("cellAudioAdd2chData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume); cellAudio.Log("cellAudioAdd2chData(portNum=%d, src=*0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -958,7 +958,7 @@ s32 cellAudioAdd6chData(u32 portNum, vm::ptr<float> src, float volume)
{ {
cellAudio.Log("cellAudioAdd6chData(portNum=%d, src=*0x%x, volume=%f)", portNum, src, volume); cellAudio.Log("cellAudioAdd6chData(portNum=%d, src=*0x%x, volume=%f)", portNum, src, volume);
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED) if (g_audio.state.load() != AUDIO_STATE_INITIALIZED)
{ {
return CELL_AUDIO_ERROR_NOT_INIT; return CELL_AUDIO_ERROR_NOT_INIT;
} }
@ -1024,7 +1024,7 @@ s32 cellAudioUnsetPersonalDevice(s32 iPersonalStream)
Module cellAudio("cellAudio", []() Module cellAudio("cellAudio", []()
{ {
g_audio.state.write_relaxed(AUDIO_STATE_NOT_INITIALIZED); g_audio.state.store(AUDIO_STATE_NOT_INITIALIZED);
g_audio.buffer = 0; g_audio.buffer = 0;
g_audio.indexes = 0; g_audio.indexes = 0;

View file

@ -398,7 +398,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED) if (file->st_status.load() == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -422,7 +422,7 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr<u64> status)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
switch (file->st_status.read_sync()) switch (file->st_status.load())
{ {
case SSS_INITIALIZED: case SSS_INITIALIZED:
case SSS_STOPPED: case SSS_STOPPED:
@ -456,7 +456,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED) if (file->st_status.load() == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -500,7 +500,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
{ {
std::unique_lock<std::mutex> lock(file->mutex); std::unique_lock<std::mutex> lock(file->mutex);
while (file->st_status.read_relaxed() == SSS_STARTED && !Emu.IsStopped()) while (file->st_status.load() == SSS_STARTED && !Emu.IsStopped())
{ {
// check free space in buffer and available data in stream // check free space in buffer and available data in stream
if (file->st_total_read - file->st_copied <= file->st_ringbuf_size - file->st_block_size && file->st_total_read < file->st_read_size) if (file->st_total_read - file->st_copied <= file->st_ringbuf_size - file->st_block_size && file->st_total_read < file->st_read_size)
@ -590,7 +590,7 @@ s32 cellFsStRead(u32 fd, vm::ptr<u8> buf, u64 size, vm::ptr<u64> rsize)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED || file->st_copyless) if (file->st_status.load() == SSS_NOT_INITIALIZED || file->st_copyless)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -624,7 +624,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED || !file->st_copyless) if (file->st_status.load() == SSS_NOT_INITIALIZED || !file->st_copyless)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -657,7 +657,7 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr<u8> addr, u64 size)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED || !file->st_copyless) if (file->st_status.load() == SSS_NOT_INITIALIZED || !file->st_copyless)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -684,7 +684,7 @@ s32 cellFsStReadWait(u32 fd, u64 size)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED) if (file->st_status.load() == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }
@ -718,7 +718,7 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, fs_st_cb_t func)
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
if (file->st_status.read_sync() == SSS_NOT_INITIALIZED) if (file->st_status.load() == SSS_NOT_INITIALIZED)
{ {
return CELL_FS_ENXIO; return CELL_FS_ENXIO;
} }

View file

@ -379,9 +379,9 @@ s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> context, u32 cmdSize, u32 ioSiz
vm::write32(context.addr(), gcm_info.context_addr); vm::write32(context.addr(), gcm_info.context_addr);
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr); auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
ctrl.put.write_relaxed(0); ctrl.put.store(0);
ctrl.get.write_relaxed(0); ctrl.get.store(0);
ctrl.ref.write_relaxed(-1); ctrl.ref.store(-1);
auto& render = Emu.GetGSManager().GetRender(); auto& render = Emu.GetGSManager().GetRender();
render.m_ctxt_addr = context.addr(); render.m_ctxt_addr = context.addr();
@ -1220,7 +1220,7 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
// Wait for rsx to "release" the new command buffer // Wait for rsx to "release" the new command buffer
while (!Emu.IsStopped()) while (!Emu.IsStopped())
{ {
u32 getPos = ctrl.get.read_sync().value(); u32 getPos = ctrl.get.load().value();
if (isInCommandBufferExcept(getPos, newCommandBuffer.first, newCommandBuffer.second)) if (isInCommandBufferExcept(getPos, newCommandBuffer.first, newCommandBuffer.second))
break; break;
std::chrono::time_point<std::chrono::system_clock> waitPoint = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> waitPoint = std::chrono::system_clock::now();
@ -1235,7 +1235,7 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
//if (0) //if (0)
//{ //{
// auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr); // auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
// be_t<u32> res = context->current - context->begin - ctrl.put.read_relaxed(); // be_t<u32> res = context->current - context->begin - ctrl.put.load();
// if (res != 0) // if (res != 0)
// { // {
@ -1245,8 +1245,8 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
// memmove(vm::get_ptr<void>(context->begin), vm::get_ptr<void>(context->current - res), res); // memmove(vm::get_ptr<void>(context->begin), vm::get_ptr<void>(context->current - res), res);
// context->current = context->begin + res; // context->current = context->begin + res;
// ctrl.put.write_relaxed(res); // ctrl.put.store(res);
// ctrl.get.write_relaxed(0); // ctrl.get.store(0);
// return CELL_OK; // return CELL_OK;
//} //}

View file

@ -411,7 +411,7 @@ s32 spursDetachLv2EventQueue(vm::ptr<CellSpurs> spurs, u8 spuPort, bool spursCre
auto mask = 1ull << spuPort; auto mask = 1ull << spuPort;
if (sdkVer >= 0x180000) if (sdkVer >= 0x180000)
{ {
if ((spurs->spuPortBits.read_relaxed() & mask) == 0) if ((spurs->spuPortBits.load() & mask) == 0)
{ {
return CELL_SPURS_CORE_ERROR_SRCH; return CELL_SPURS_CORE_ERROR_SRCH;
} }
@ -438,7 +438,7 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
spursPpuThreadExit(CPU, 0); spursPpuThreadExit(CPU, 0);
} }
if (spurs->handlerExiting.read_relaxed()) if (spurs->handlerExiting.load())
{ {
if (s32 rc = sys_lwmutex_unlock(CPU, spurs.of(&CellSpurs::mutex))) if (s32 rc = sys_lwmutex_unlock(CPU, spurs.of(&CellSpurs::mutex)))
{ {
@ -449,20 +449,20 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
} }
// Find a runnable workload // Find a runnable workload
spurs->handlerDirty.write_relaxed(0); spurs->handlerDirty.store(0);
if (spurs->exception == 0) if (spurs->exception == 0)
{ {
bool foundRunnableWorkload = false; bool foundRunnableWorkload = false;
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
if (spurs->wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE && if (spurs->wklState1[i].load() == SPURS_WKL_STATE_RUNNABLE &&
*((u64*)spurs->wklInfo1[i].priority) != 0 && *((u64*)spurs->wklInfo1[i].priority) != 0 &&
spurs->wklMaxContention[i].read_relaxed() & 0x0F) spurs->wklMaxContention[i].load() & 0x0F)
{ {
if (spurs->wklReadyCount1[i].read_relaxed() || if (spurs->wklReadyCount1[i].load() ||
spurs->wklSignal1.read_relaxed() & (0x8000u >> i) || spurs->wklSignal1.load() & (0x8000u >> i) ||
(spurs->wklFlag.flag.read_relaxed() == 0 && (spurs->wklFlag.flag.load() == 0 &&
spurs->wklFlagReceiver.read_relaxed() == (u8)i)) spurs->wklFlagReceiver.load() == (u8)i))
{ {
foundRunnableWorkload = true; foundRunnableWorkload = true;
break; break;
@ -474,14 +474,14 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
{ {
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
if (spurs->wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE && if (spurs->wklState2[i].load() == SPURS_WKL_STATE_RUNNABLE &&
*((u64*)spurs->wklInfo2[i].priority) != 0 && *((u64*)spurs->wklInfo2[i].priority) != 0 &&
spurs->wklMaxContention[i].read_relaxed() & 0xF0) spurs->wklMaxContention[i].load() & 0xF0)
{ {
if (spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed() || if (spurs->wklIdleSpuCountOrReadyCount2[i].load() ||
spurs->wklSignal2.read_relaxed() & (0x8000u >> i) || spurs->wklSignal2.load() & (0x8000u >> i) ||
(spurs->wklFlag.flag.read_relaxed() == 0 && (spurs->wklFlag.flag.load() == 0 &&
spurs->wklFlagReceiver.read_relaxed() == (u8)i + 0x10)) spurs->wklFlagReceiver.load() == (u8)i + 0x10))
{ {
foundRunnableWorkload = true; foundRunnableWorkload = true;
break; break;
@ -497,8 +497,8 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
// If we reach it means there are no runnable workloads in this SPURS instance. // If we reach it means there are no runnable workloads in this SPURS instance.
// Wait until some workload becomes ready. // Wait until some workload becomes ready.
spurs->handlerWaiting.write_relaxed(1); spurs->handlerWaiting.store(1);
if (spurs->handlerDirty.read_relaxed() == 0) if (spurs->handlerDirty.load() == 0)
{ {
if (s32 rc = sys_lwcond_wait(CPU, spurs.of(&CellSpurs::cond), 0)) if (s32 rc = sys_lwcond_wait(CPU, spurs.of(&CellSpurs::cond), 0))
{ {
@ -506,7 +506,7 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
} }
} }
spurs->handlerWaiting.write_relaxed(0); spurs->handlerWaiting.store(0);
} }
// If we reach here then a runnable workload was found // If we reach here then a runnable workload was found
@ -557,7 +557,7 @@ void spursHandlerEntry(PPUThread& CPU)
if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0) if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0)
{ {
assert(spurs->handlerExiting.read_relaxed() == 1 || Emu.IsStopped()); assert(spurs->handlerExiting.load() == 1 || Emu.IsStopped());
spursPpuThreadExit(CPU, 0); spursPpuThreadExit(CPU, 0);
} }
} }
@ -609,12 +609,12 @@ s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
} }
const u8 wklState = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->wklState1[wid].read_relaxed() : spurs->wklState2[wid & 0x0F].read_relaxed(); const u8 wklState = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->wklState1[wid].load() : spurs->wklState2[wid & 0x0F].load();
if (wklState != SPURS_WKL_STATE_REMOVABLE) if (wklState != SPURS_WKL_STATE_REMOVABLE)
{ {
@ -628,14 +628,14 @@ s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs
{ {
wklF.hook(CPU, spurs, wid, wklF.hookArg); wklF.hook(CPU, spurs, wid, wklF.hookArg);
assert(wklEvent.read_relaxed() & 0x01); assert(wklEvent.load() & 0x01);
assert(wklEvent.read_relaxed() & 0x02); assert(wklEvent.load() & 0x02);
assert((wklEvent.read_relaxed() & 0x20) == 0); assert((wklEvent.load() & 0x20) == 0);
wklEvent |= 0x20; wklEvent |= 0x20;
} }
s32 rc = CELL_OK; s32 rc = CELL_OK;
if (!wklF.hook || wklEvent.read_relaxed() & 0x10) if (!wklF.hook || wklEvent.load() & 0x10)
{ {
assert(wklF.x28 == 2); assert(wklF.x28 == 2);
rc = sys_semaphore_post((u32)wklF.sem, 1); rc = sys_semaphore_post((u32)wklF.sem, 1);
@ -1028,7 +1028,7 @@ s32 spursInit(
if (!isSecond) if (!isSecond)
{ {
spurs->wklEnabled.write_relaxed(0xffff); spurs->wklEnabled.store(0xffff);
} }
// Initialise trace // Initialise trace
@ -1043,7 +1043,7 @@ s32 spursInit(
spurs->wklInfoSysSrv.addr.set(SPURS_IMG_ADDR_SYS_SRV_WORKLOAD); spurs->wklInfoSysSrv.addr.set(SPURS_IMG_ADDR_SYS_SRV_WORKLOAD);
spurs->wklInfoSysSrv.size = 0x2200; spurs->wklInfoSysSrv.size = 0x2200;
spurs->wklInfoSysSrv.arg = 0; spurs->wklInfoSysSrv.arg = 0;
spurs->wklInfoSysSrv.uniqueId.write_relaxed(0xff); spurs->wklInfoSysSrv.uniqueId.store(0xff);
auto sys_semaphore_attribute_initialize = [](vm::ptr<sys_semaphore_attribute_t> attr) auto sys_semaphore_attribute_initialize = [](vm::ptr<sys_semaphore_attribute_t> attr)
{ {
@ -1221,11 +1221,11 @@ s32 spursInit(
} }
spurs->flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_32_WORKLOADS : 0); spurs->flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_32_WORKLOADS : 0);
spurs->wklFlagReceiver.write_relaxed(0xff); spurs->wklFlagReceiver.store(0xff);
spurs->wklFlag.flag.write_relaxed(-1); spurs->wklFlag.flag.store(-1);
spurs->handlerDirty.write_relaxed(0); spurs->handlerDirty.store(0);
spurs->handlerWaiting.write_relaxed(0); spurs->handlerWaiting.store(0);
spurs->handlerExiting.write_relaxed(0); spurs->handlerExiting.store(0);
spurs->ppuPriority = ppuPriority; spurs->ppuPriority = ppuPriority;
// Create the SPURS event helper thread // Create the SPURS event helper thread
@ -1586,12 +1586,12 @@ s32 cellSpursFinalize(vm::ptr<CellSpurs> spurs)
return CELL_SPURS_CORE_ERROR_ALIGN; return CELL_SPURS_CORE_ERROR_ALIGN;
} }
if (spurs->handlerExiting.read_relaxed()) if (spurs->handlerExiting.load())
{ {
return CELL_SPURS_CORE_ERROR_STAT; return CELL_SPURS_CORE_ERROR_STAT;
} }
u32 wklEnabled = spurs->wklEnabled.read_relaxed(); u32 wklEnabled = spurs->wklEnabled.load();
if (spurs->flags1 & SF1_32_WORKLOADS) if (spurs->flags1 & SF1_32_WORKLOADS)
{ {
@ -1690,7 +1690,7 @@ s32 cellSpursSetMaxContention(vm::ptr<CellSpurs> spurs, u32 wid, u32 maxContenti
return CELL_SPURS_CORE_ERROR_INVAL; return CELL_SPURS_CORE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_CORE_ERROR_SRCH; return CELL_SPURS_CORE_ERROR_SRCH;
} }
@ -1734,7 +1734,7 @@ s32 cellSpursSetPriorities(vm::ptr<CellSpurs> spurs, u32 wid, vm::cptr<u8> prior
return CELL_SPURS_CORE_ERROR_INVAL; return CELL_SPURS_CORE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_CORE_ERROR_SRCH; return CELL_SPURS_CORE_ERROR_SRCH;
} }
@ -1764,8 +1764,8 @@ s32 cellSpursSetPriorities(vm::ptr<CellSpurs> spurs, u32 wid, vm::cptr<u8> prior
auto& wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->wklInfo1[wid] : spurs->wklInfo2[wid]; auto& wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->wklInfo1[wid] : spurs->wklInfo2[wid];
*((be_t<u64>*)wklInfo.priority) = prio; *((be_t<u64>*)wklInfo.priority) = prio;
spurs->sysSrvMsgUpdateWorkload.write_relaxed(0xFF); spurs->sysSrvMsgUpdateWorkload.store(0xFF);
spurs->sysSrvMessage.write_relaxed(0xFF); spurs->sysSrvMessage.store(0xFF);
return CELL_OK; return CELL_OK;
} }
@ -1907,7 +1907,7 @@ void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs)
if (init) if (init)
{ {
spurs->sysSrvMessage.write_relaxed(0xFF); spurs->sysSrvMessage.store(0xFF);
if (s32 rc = sys_semaphore_wait((u32)spurs->semPrv, 0)) if (s32 rc = sys_semaphore_wait((u32)spurs->semPrv, 0))
{ {
@ -2241,9 +2241,9 @@ s32 spursAddWorkload(
{ {
assert((spurs->wklCurrentContention[wnum] & 0xf) == 0); assert((spurs->wklCurrentContention[wnum] & 0xf) == 0);
assert((spurs->wklPendingContention[wnum] & 0xf) == 0); assert((spurs->wklPendingContention[wnum] & 0xf) == 0);
spurs->wklState1[wnum].write_relaxed(1); spurs->wklState1[wnum].store(1);
spurs->wklStatus1[wnum] = 0; spurs->wklStatus1[wnum] = 0;
spurs->wklEvent1[wnum].write_relaxed(0); spurs->wklEvent1[wnum].store(0);
spurs->wklInfo1[wnum].addr = pm; spurs->wklInfo1[wnum].addr = pm;
spurs->wklInfo1[wnum].arg = data; spurs->wklInfo1[wnum].arg = data;
spurs->wklInfo1[wnum].size = size; spurs->wklInfo1[wnum].size = size;
@ -2267,19 +2267,19 @@ s32 spursAddWorkload(
if ((spurs->flags1 & SF1_32_WORKLOADS) == 0) if ((spurs->flags1 & SF1_32_WORKLOADS) == 0)
{ {
spurs->wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0); spurs->wklIdleSpuCountOrReadyCount2[wnum].store(0);
spurs->wklMinContention[wnum] = minContention > 8 ? 8 : minContention; spurs->wklMinContention[wnum] = minContention > 8 ? 8 : minContention;
} }
spurs->wklReadyCount1[wnum].write_relaxed(0); spurs->wklReadyCount1[wnum].store(0);
} }
else else
{ {
assert((spurs->wklCurrentContention[index] & 0xf0) == 0); assert((spurs->wklCurrentContention[index] & 0xf0) == 0);
assert((spurs->wklPendingContention[index] & 0xf0) == 0); assert((spurs->wklPendingContention[index] & 0xf0) == 0);
spurs->wklState2[index].write_relaxed(1); spurs->wklState2[index].store(1);
spurs->wklStatus2[index] = 0; spurs->wklStatus2[index] = 0;
spurs->wklEvent2[index].write_relaxed(0); spurs->wklEvent2[index].store(0);
spurs->wklInfo2[index].addr = pm; spurs->wklInfo2[index].addr = pm;
spurs->wklInfo2[index].arg = data; spurs->wklInfo2[index].arg = data;
spurs->wklInfo2[index].size = size; spurs->wklInfo2[index].size = size;
@ -2301,7 +2301,7 @@ s32 spursAddWorkload(
spurs->wklEvent2[index] |= 2; spurs->wklEvent2[index] |= 2;
} }
spurs->wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0); spurs->wklIdleSpuCountOrReadyCount2[wnum].store(0);
} }
if (wnum <= 15) if (wnum <= 15)
@ -2327,7 +2327,7 @@ s32 spursAddWorkload(
u32 res_wkl; u32 res_wkl;
CellSpurs::WorkloadInfo& wkl = wnum <= 15 ? spurs->wklInfo1[wnum] : spurs->wklInfo2[wnum & 0xf]; CellSpurs::WorkloadInfo& wkl = wnum <= 15 ? spurs->wklInfo1[wnum] : spurs->wklInfo2[wnum & 0xf];
spurs->wklMskB.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t<u32>& v) spurs->wklMskB.atomic_op([spurs, &wkl, wnum, &res_wkl](be_t<u32>& v)
{ {
const u32 mask = v & ~(0x80000000u >> wnum); const u32 mask = v & ~(0x80000000u >> wnum);
res_wkl = 0; res_wkl = 0;
@ -2340,12 +2340,12 @@ s32 spursAddWorkload(
if (current.addr == wkl.addr) if (current.addr == wkl.addr)
{ {
// if a workload with identical policy module found // if a workload with identical policy module found
res_wkl = current.uniqueId.read_relaxed(); res_wkl = current.uniqueId.load();
break; break;
} }
else else
{ {
k |= 0x80000000 >> current.uniqueId.read_relaxed(); k |= 0x80000000 >> current.uniqueId.load();
res_wkl = cntlz32(~k); res_wkl = cntlz32(~k);
} }
} }
@ -2437,7 +2437,7 @@ s32 cellSpursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
spurs->handlerDirty.exchange(1); spurs->handlerDirty.exchange(1);
if (spurs->handlerWaiting.read_sync()) if (spurs->handlerWaiting.load())
{ {
spursSignalToHandlerThread(CPU, spurs); spursSignalToHandlerThread(CPU, spurs);
} }
@ -2465,7 +2465,7 @@ s32 cellSpursSendWorkloadSignal(vm::ptr<CellSpurs> spurs, u32 wid)
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
} }
@ -2475,7 +2475,7 @@ s32 cellSpursSendWorkloadSignal(vm::ptr<CellSpurs> spurs, u32 wid)
return CELL_SPURS_POLICY_MODULE_ERROR_STAT; return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
} }
if (spurs->wklState(wid).read_relaxed() != SPURS_WKL_STATE_RUNNABLE) if (spurs->wklState(wid).load() != SPURS_WKL_STATE_RUNNABLE)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_STAT; return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
} }
@ -2531,12 +2531,12 @@ s32 cellSpursReadyCountStore(vm::ptr<CellSpurs> spurs, u32 wid, u32 value)
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
} }
if (spurs->exception.data() || spurs->wklState(wid).read_relaxed() != 2) if (spurs->exception.data() || spurs->wklState(wid).load() != 2)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_STAT; return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
} }
@ -2594,7 +2594,7 @@ s32 cellSpursGetWorkloadData(vm::ptr<CellSpurs> spurs, vm::ptr<u64> data, u32 wi
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
} }
@ -2657,7 +2657,7 @@ s32 _cellSpursWorkloadFlagReceiver(vm::ptr<CellSpurs> spurs, u32 wid, u32 is_set
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
} }
if ((spurs->wklEnabled.read_relaxed() & (0x80000000u >> wid)) == 0) if ((spurs->wklEnabled.load() & (0x80000000u >> wid)) == 0)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
} }
@ -2667,18 +2667,20 @@ s32 _cellSpursWorkloadFlagReceiver(vm::ptr<CellSpurs> spurs, u32 wid, u32 is_set
return CELL_SPURS_POLICY_MODULE_ERROR_STAT; return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
} }
if (s32 res = spurs->wklFlag.flag.atomic_op_sync(0, [spurs, wid, is_set](be_t<u32>& flag) -> s32 _mm_mfence();
if (s32 res = spurs->wklFlag.flag.atomic_op([spurs, wid, is_set](be_t<u32>& flag) -> s32
{ {
if (is_set) if (is_set)
{ {
if (spurs->wklFlagReceiver.read_relaxed() != 0xff) if (spurs->wklFlagReceiver.load() != 0xff)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_BUSY; return CELL_SPURS_POLICY_MODULE_ERROR_BUSY;
} }
} }
else else
{ {
if (spurs->wklFlagReceiver.read_relaxed() != wid) if (spurs->wklFlagReceiver.load() != wid)
{ {
return CELL_SPURS_POLICY_MODULE_ERROR_PERM; return CELL_SPURS_POLICY_MODULE_ERROR_PERM;
} }

View file

@ -194,21 +194,21 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
// The system service has the highest priority. Select the system service if // The system service has the highest priority. Select the system service if
// the system service message bit for this SPU is set. // the system service message bit for this SPU is set.
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { if (spurs->sysSrvMessage.load() & (1 << ctxt->spuNum)) {
ctxt->spuIdling = 0; ctxt->spuIdling = 0;
if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
// Clear the message bit // Clear the message bit
spurs->sysSrvMessage.write_relaxed(spurs->sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum)); spurs->sysSrvMessage.store(spurs->sysSrvMessage.load() & ~(1 << ctxt->spuNum));
} }
} else { } else {
// Caclulate the scheduling weight for each workload // Caclulate the scheduling weight for each workload
u16 maxWeight = 0; u16 maxWeight = 0;
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i);
u16 wklSignal = spurs->wklSignal1.read_relaxed() & (0x8000 >> i); u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver.load() == i ? 1 : 0 : 0;
u8 readyCount = spurs->wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].read_relaxed(); u8 readyCount = spurs->wklReadyCount1[i].load() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load();
u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed(); u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].load() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load();
u8 requestCount = readyCount + idleSpuCount; u8 requestCount = readyCount + idleSpuCount;
// For a workload to be considered for scheduling: // For a workload to be considered for scheduling:
@ -218,7 +218,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
// 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount)
// OR the workload must be signalled // OR the workload must be signalled
// OR the workload flag is 0 and the workload is configured as the wokload flag receiver // OR the workload flag is 0 and the workload is configured as the wokload flag receiver
if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].read_relaxed() > contention[i]) { if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].load() > contention[i]) {
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) {
// The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority:
// 1. Wokload signal set or workload flag or ready count > contention // 1. Wokload signal set or workload flag or ready count > contention
@ -253,12 +253,12 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { if (!isPoll || wklSelectedId == ctxt->wklCurrentId) {
// Clear workload signal for the selected workload // Clear workload signal for the selected workload
spurs->wklSignal1.write_relaxed(spurs->wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)); spurs->wklSignal1.store(spurs->wklSignal1.load() & ~(0x8000 >> wklSelectedId));
spurs->wklSignal2.write_relaxed(spurs->wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)); spurs->wklSignal2.store(spurs->wklSignal1.load() & ~(0x80000000u >> wklSelectedId));
// If the selected workload is the wklFlag workload then pull the wklFlag to all 1s // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s
if (wklSelectedId == spurs->wklFlagReceiver.read_relaxed()) { if (wklSelectedId == spurs->wklFlagReceiver.load()) {
spurs->wklFlag.flag.write_relaxed(0xFFFFFFFF); spurs->wklFlag.flag.store(0xFFFFFFFF);
} }
} }
} }
@ -353,12 +353,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
// The system service has the highest priority. Select the system service if // The system service has the highest priority. Select the system service if
// the system service message bit for this SPU is set. // the system service message bit for this SPU is set.
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { if (spurs->sysSrvMessage.load() & (1 << ctxt->spuNum)) {
// Not sure what this does. Possibly Mark the SPU as in use. // Not sure what this does. Possibly Mark the SPU as in use.
ctxt->spuIdling = 0; ctxt->spuIdling = 0;
if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
// Clear the message bit // Clear the message bit
spurs->sysSrvMessage.write_relaxed(spurs->sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum)); spurs->sysSrvMessage.store(spurs->sysSrvMessage.load() & ~(1 << ctxt->spuNum));
} }
} else { } else {
// Caclulate the scheduling weight for each workload // Caclulate the scheduling weight for each workload
@ -367,10 +367,10 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
auto j = i & 0x0F; auto j = i & 0x0F;
u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j);
u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4;
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].read_relaxed() & 0x0F : spurs->wklMaxContention[j].read_relaxed() >> 4; u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].load() & 0x0F : spurs->wklMaxContention[j].load() >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->wklSignal2.read_relaxed() & (0x8000 >> j); u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver.load() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[j].read_relaxed(); u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].load() : spurs->wklIdleSpuCountOrReadyCount2[j].load();
// For a workload to be considered for scheduling: // For a workload to be considered for scheduling:
// 1. Its priority must be greater than 0 // 1. Its priority must be greater than 0
@ -405,12 +405,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { if (!isPoll || wklSelectedId == ctxt->wklCurrentId) {
// Clear workload signal for the selected workload // Clear workload signal for the selected workload
spurs->wklSignal1.write_relaxed(spurs->wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)); spurs->wklSignal1.store(spurs->wklSignal1.load() & ~(0x8000 >> wklSelectedId));
spurs->wklSignal2.write_relaxed(spurs->wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)); spurs->wklSignal2.store(spurs->wklSignal1.load() & ~(0x80000000u >> wklSelectedId));
// If the selected workload is the wklFlag workload then pull the wklFlag to all 1s // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s
if (wklSelectedId == spurs->wklFlagReceiver.read_relaxed()) { if (wklSelectedId == spurs->wklFlagReceiver.load()) {
spurs->wklFlag.flag.write_relaxed(0xFFFFFFFF); spurs->wklFlag.flag.store(0xFFFFFFFF);
} }
} }
} }
@ -492,7 +492,7 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) {
} }
ctxt->wklCurrentAddr = wklInfo->addr; ctxt->wklCurrentAddr = wklInfo->addr;
ctxt->wklCurrentUniqueId = wklInfo->uniqueId.read_relaxed(); ctxt->wklCurrentUniqueId = wklInfo->uniqueId.load();
} }
if (!isKernel2) { if (!isKernel2) {
@ -624,7 +624,7 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
// Check if any workloads can be scheduled // Check if any workloads can be scheduled
bool foundReadyWorkload = false; bool foundReadyWorkload = false;
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { if (spurs->sysSrvMessage.load() & (1 << ctxt->spuNum)) {
foundReadyWorkload = true; foundReadyWorkload = true;
} else { } else {
if (spurs->flags1 & SF1_32_WORKLOADS) { if (spurs->flags1 & SF1_32_WORKLOADS) {
@ -632,11 +632,11 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
u32 j = i & 0x0F; u32 j = i & 0x0F;
u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j);
u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4;
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].read_relaxed() & 0x0F : spurs->wklMaxContention[j].read_relaxed() >> 4; u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].load() & 0x0F : spurs->wklMaxContention[j].load() >> 4;
u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklCurrentContention[j] & 0x0F : spurs->wklCurrentContention[j] >> 4; u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklCurrentContention[j] & 0x0F : spurs->wklCurrentContention[j] >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->wklSignal2.read_relaxed() & (0x8000 >> j); u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.load() & (0x8000 >> j) : spurs->wklSignal2.load() & (0x8000 >> j);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver.load() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[j].read_relaxed(); u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].load() : spurs->wklIdleSpuCountOrReadyCount2[j].load();
if (runnable && priority > 0 && maxContention > contention) { if (runnable && priority > 0 && maxContention > contention) {
if (wklFlag || wklSignal || readyCount > contention) { if (wklFlag || wklSignal || readyCount > contention) {
@ -648,13 +648,13 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
} else { } else {
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i);
u16 wklSignal = spurs->wklSignal1.read_relaxed() & (0x8000 >> i); u16 wklSignal = spurs->wklSignal1.load() & (0x8000 >> i);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 wklFlag = spurs->wklFlag.flag.load() == 0 ? spurs->wklFlagReceiver.load() == i ? 1 : 0 : 0;
u8 readyCount = spurs->wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].read_relaxed(); u8 readyCount = spurs->wklReadyCount1[i].load() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].load();
u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed(); u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].load() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].load();
u8 requestCount = readyCount + idleSpuCount; u8 requestCount = readyCount + idleSpuCount;
if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].read_relaxed() > spurs->wklCurrentContention[i]) { if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].load() > spurs->wklCurrentContention[i]) {
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->wklCurrentContention[i])) { if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->wklCurrentContention[i])) {
foundReadyWorkload = true; foundReadyWorkload = true;
break; break;
@ -802,7 +802,7 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt)
} }
// Update workload message // Update workload message
if (spurs->sysSrvMsgUpdateWorkload.read_relaxed() & (1 << ctxt->spuNum)) { if (spurs->sysSrvMsgUpdateWorkload.load() & (1 << ctxt->spuNum)) {
spurs->sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum); spurs->sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum);
updateWorkload = true; updateWorkload = true;
} }
@ -847,7 +847,7 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
// Copy the priority of the workload for this SPU and its unique id to the LS // Copy the priority of the workload for this SPU and its unique id to the LS
ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum]; ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum];
ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId.read_relaxed(); ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId.load();
if (spurs->flags1 & SF1_32_WORKLOADS) { if (spurs->flags1 & SF1_32_WORKLOADS) {
auto wklInfo2 = vm::get_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x30200); auto wklInfo2 = vm::get_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x30200);
@ -865,7 +865,7 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
// Update workload status and runnable flag based on the workload state // Update workload status and runnable flag based on the workload state
auto wklStatus = spurs->wklStatus1[i]; auto wklStatus = spurs->wklStatus1[i];
if (spurs->wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { if (spurs->wklState1[i].load() == SPURS_WKL_STATE_RUNNABLE) {
spurs->wklStatus1[i] |= 1 << ctxt->spuNum; spurs->wklStatus1[i] |= 1 << ctxt->spuNum;
ctxt->wklRunnable1 |= 0x8000 >> i; ctxt->wklRunnable1 |= 0x8000 >> i;
} else { } else {
@ -874,9 +874,9 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
// If the workload is shutting down and if this is the last SPU from which it is being removed then // If the workload is shutting down and if this is the last SPU from which it is being removed then
// add it to the shutdown bit set // add it to the shutdown bit set
if (spurs->wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { if (spurs->wklState1[i].load() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus1[i] == 0)) { if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus1[i] == 0)) {
spurs->wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); spurs->wklState1[i].store(SPURS_WKL_STATE_REMOVABLE);
wklShutdownBitSet |= 0x80000000u >> i; wklShutdownBitSet |= 0x80000000u >> i;
} }
} }
@ -884,7 +884,7 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
if (spurs->flags1 & SF1_32_WORKLOADS) { if (spurs->flags1 & SF1_32_WORKLOADS) {
// Update workload status and runnable flag based on the workload state // Update workload status and runnable flag based on the workload state
wklStatus = spurs->wklStatus2[i]; wklStatus = spurs->wklStatus2[i];
if (spurs->wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { if (spurs->wklState2[i].load() == SPURS_WKL_STATE_RUNNABLE) {
spurs->wklStatus2[i] |= 1 << ctxt->spuNum; spurs->wklStatus2[i] |= 1 << ctxt->spuNum;
ctxt->wklRunnable2 |= 0x8000 >> i; ctxt->wklRunnable2 |= 0x8000 >> i;
} else { } else {
@ -893,9 +893,9 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
// If the workload is shutting down and if this is the last SPU from which it is being removed then // If the workload is shutting down and if this is the last SPU from which it is being removed then
// add it to the shutdown bit set // add it to the shutdown bit set
if (spurs->wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { if (spurs->wklState2[i].load() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus2[i] == 0)) { if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus2[i] == 0)) {
spurs->wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); spurs->wklState2[i].store(SPURS_WKL_STATE_REMOVABLE);
wklShutdownBitSet |= 0x8000 >> i; wklShutdownBitSet |= 0x8000 >> i;
} }
} }
@ -924,14 +924,14 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
if (wklShutdownBitSet & (0x80000000u >> i)) { if (wklShutdownBitSet & (0x80000000u >> i)) {
spurs->wklEvent1[i] |= 0x01; spurs->wklEvent1[i] |= 0x01;
if (spurs->wklEvent1[i].read_relaxed() & 0x02 || spurs->wklEvent1[i].read_relaxed() & 0x10) { if (spurs->wklEvent1[i].load() & 0x02 || spurs->wklEvent1[i].load() & 0x10) {
wklNotifyBitSet |= 0x80000000u >> i; wklNotifyBitSet |= 0x80000000u >> i;
} }
} }
if (wklShutdownBitSet & (0x8000 >> i)) { if (wklShutdownBitSet & (0x8000 >> i)) {
spurs->wklEvent2[i] |= 0x01; spurs->wklEvent2[i] |= 0x01;
if (spurs->wklEvent2[i].read_relaxed() & 0x02 || spurs->wklEvent2[i].read_relaxed() & 0x10) { if (spurs->wklEvent2[i].load() & 0x02 || spurs->wklEvent2[i].load() & 0x10) {
wklNotifyBitSet |= 0x8000 >> i; wklNotifyBitSet |= 0x8000 >> i;
} }
} }
@ -1035,10 +1035,10 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
if (wklId >= CELL_SPURS_MAX_WORKLOAD) { if (wklId >= CELL_SPURS_MAX_WORKLOAD) {
spurs->wklCurrentContention[wklId & 0x0F] -= 0x10; spurs->wklCurrentContention[wklId & 0x0F] -= 0x10;
spurs->wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); spurs->wklReadyCount1[wklId & 0x0F].store(spurs->wklReadyCount1[wklId & 0x0F].load() - 1);
} else { } else {
spurs->wklCurrentContention[wklId & 0x0F] -= 0x01; spurs->wklCurrentContention[wklId & 0x0F] -= 0x01;
spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].store(spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].load() - 1);
} }
memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128); memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128);
@ -1317,14 +1317,14 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
vm::reservation_op(vm::cast(kernelCtxt->spurs.addr()), 128, [&]() { vm::reservation_op(vm::cast(kernelCtxt->spurs.addr()), 128, [&]() {
auto spurs = kernelCtxt->spurs.priv_ptr(); auto spurs = kernelCtxt->spurs.priv_ptr();
s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed(); s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[kernelCtxt->wklCurrentId].load() : spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].load();
readyCount += numNewlyReadyTasks; readyCount += numNewlyReadyTasks;
readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount; readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount;
if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) { if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) {
spurs->wklReadyCount1[kernelCtxt->wklCurrentId].write_relaxed(readyCount); spurs->wklReadyCount1[kernelCtxt->wklCurrentId].store(readyCount);
} else { } else {
spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].write_relaxed(readyCount); spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].store(readyCount);
} }
memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128); memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128);

File diff suppressed because it is too large Load diff

View file

@ -31,67 +31,216 @@ enum
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ??? CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ???
}; };
union set_alignment(4) CellSyncMutex struct set_alignment(4) sync_mutex_t // CellSyncMutex sync var
{ {
struct sync_t be_t<u16> rel;
{ be_t<u16> acq;
be_t<u16> cnt_rel; // increased when mutex is unlocked
be_t<u16> cnt_acq; // increased when mutex is locked
};
struct be_t<u16> acquire()
{ {
atomic_be_t<u16> rel; return acq++;
atomic_be_t<u16> acq;
} }
cnt;
atomic_be_t<sync_t> sync_var; bool try_lock()
{
return acq++ == rel;
}
void unlock()
{
rel++;
}
}; };
using CellSyncMutex = atomic_be_t<sync_mutex_t>;
CHECK_SIZE_ALIGN(CellSyncMutex, 4, 4); CHECK_SIZE_ALIGN(CellSyncMutex, 4, 4);
struct set_alignment(4) CellSyncBarrier struct set_alignment(4) sync_barrier_t // CellSyncBarrier sync var
{ {
struct data_t be_t<s16> value;
be_t<s16> count;
bool try_notify()
{ {
be_t<s16> m_value; // extract m_value (repeat if < 0), increase, compare with second s16, set sign bit if equal, insert it back
be_t<s16> m_count; s16 v = value;
if (v < 0)
{
return false;
}
if (++v == count)
{
v |= 0x8000;
}
value = v;
return true;
}; };
atomic_be_t<data_t> data; bool try_wait()
{
// extract m_value (repeat if >= 0), decrease it, set 0 if == 0x8000, insert it back
s16 v = value;
if (v >= 0)
{
return false;
}
if (--v == -0x8000)
{
v = 0;
}
value = v;
return true;
}
}; };
using CellSyncBarrier = atomic_be_t<sync_barrier_t>;
CHECK_SIZE_ALIGN(CellSyncBarrier, 4, 4); CHECK_SIZE_ALIGN(CellSyncBarrier, 4, 4);
struct sync_rwm_t // CellSyncRwm sync var
{
be_t<u16> readers;
be_t<u16> writers;
bool try_read_begin()
{
if (writers.data())
{
return false;
}
readers++;
return true;
}
bool try_read_end()
{
if (!readers.data())
{
return false;
}
readers--;
return true;
}
bool try_write_begin()
{
if (writers.data())
{
return false;
}
writers = 1;
return true;
}
};
struct set_alignment(16) CellSyncRwm struct set_alignment(16) CellSyncRwm
{ {
struct data_t atomic_be_t<sync_rwm_t> ctrl; // sync var
{
be_t<u16> m_readers;
be_t<u16> m_writers;
};
atomic_be_t<data_t> data; be_t<u32> size;
be_t<u32> m_size; vm::bptr<void, u64> buffer;
vm::bptr<void, u64> m_buffer;
}; };
CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16); CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16);
struct sync_queue_t // CellSyncQueue sync var
{
be_t<u32> m_v1;
be_t<u32> m_v2;
bool try_push(u32 depth, u32& position)
{
const u32 v1 = m_v1;
const u32 v2 = m_v2;
// compare 5th byte with zero (break if not zero)
// compare (second u32 (u24) + first byte) with depth (break if greater or equal)
if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth)
{
return false;
}
// extract first u32 (u24) (-> position), calculate (position + 1) % depth, insert it back
// insert 1 in 5th u8
// extract second u32 (u24), increase it, insert it back
position = (v1 & 0xffffff);
m_v1 = (v1 & 0xff000000) | ((position + 1) % depth);
m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1);
return true;
}
bool try_pop(u32 depth, u32& position)
{
const u32 v1 = m_v1;
const u32 v2 = m_v2;
// extract first u8, repeat if not zero
// extract second u32 (u24), subtract 5th u8, compare with zero, repeat if less or equal
if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24)))
{
return false;
}
// insert 1 in first u8
// extract first u32 (u24), add depth, subtract second u32 (u24), calculate (% depth), save to position
// extract second u32 (u24), decrease it, insert it back
m_v1 = 0x1000000 | v1;
position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth;
m_v2 = (v2 & 0xff000000) | ((v2 & 0xffffff) - 1);
return true;
}
bool try_peek(u32 depth, u32& position)
{
const u32 v1 = m_v1;
const u32 v2 = m_v2;
if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24)))
{
return false;
}
m_v1 = 0x1000000 | v1;
position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth;
return true;
}
};
struct set_alignment(32) CellSyncQueue struct set_alignment(32) CellSyncQueue
{ {
struct data_t atomic_be_t<sync_queue_t> ctrl;
{
be_t<u32> m_v1;
be_t<u32> m_v2;
};
atomic_be_t<data_t> data; be_t<u32> size;
be_t<u32> m_size; be_t<u32> depth;
be_t<u32> m_depth; vm::bptr<u8, u64> buffer;
vm::bptr<u8, u64> m_buffer;
be_t<u64> reserved; be_t<u64> reserved;
u32 check_depth()
{
const auto data = ctrl.load();
if ((data.m_v1 & 0xffffff) > depth || (data.m_v2 & 0xffffff) > depth)
{
throw __FUNCTION__;
}
return depth;
}
}; };
CHECK_SIZE_ALIGN(CellSyncQueue, 32, 32); CHECK_SIZE_ALIGN(CellSyncQueue, 32, 32);
@ -191,14 +340,6 @@ struct set_alignment(128) CellSyncLFQueue
CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128); CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128);
s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex);
s32 syncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count);
s32 syncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer_size);
s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth);
s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal); s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal);
s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue); s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue);
s32 syncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue); s32 syncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue);

View file

@ -343,7 +343,7 @@ int cellSurMixerCreate(vm::cptr<CellSurMixerConfig> config)
ppu.InitRegs(); ppu.InitRegs();
ppu.DoRun(); ppu.DoRun();
while (port.state.read_relaxed() != AUDIO_PORT_STATE_CLOSED && !Emu.IsStopped()) while (port.state.load() != AUDIO_PORT_STATE_CLOSED && !Emu.IsStopped())
{ {
if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack) if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack)
{ {
@ -351,7 +351,7 @@ int cellSurMixerCreate(vm::cptr<CellSurMixerConfig> config)
continue; continue;
} }
if (port.state.read_relaxed() == AUDIO_PORT_STATE_STARTED) if (port.state.load() == AUDIO_PORT_STATE_STARTED)
{ {
//u64 stamp0 = get_system_time(); //u64 stamp0 = get_system_time();

View file

@ -125,7 +125,7 @@ s32 sys_lwmutex_destroy(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
sysPrxForUser.Log("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex); sysPrxForUser.Log("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex);
// check to prevent recursive locking in the next call // check to prevent recursive locking in the next call
if (lwmutex->vars.owner.read_relaxed() == CPU.GetId()) if (lwmutex->vars.owner.load() == CPU.GetId())
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
@ -184,7 +184,7 @@ s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout
// recursive locking succeeded // recursive locking succeeded
lwmutex->recursive_count++; lwmutex->recursive_count++;
lwmutex->lock_var.read_sync(); _mm_mfence();
return CELL_OK; return CELL_OK;
} }
@ -197,7 +197,7 @@ s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout
for (u32 i = 0; i < 300; i++) for (u32 i = 0; i < 300; i++)
{ {
if (lwmutex->vars.owner.read_relaxed() == lwmutex_free) if (lwmutex->vars.owner.load() == lwmutex_free)
{ {
if (lwmutex->vars.owner.compare_and_swap_test(lwmutex_free, tid)) if (lwmutex->vars.owner.compare_and_swap_test(lwmutex_free, tid))
{ {
@ -278,7 +278,7 @@ s32 sys_lwmutex_trylock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
// recursive locking succeeded // recursive locking succeeded
lwmutex->recursive_count++; lwmutex->recursive_count++;
lwmutex->lock_var.read_sync(); _mm_mfence();
return CELL_OK; return CELL_OK;
} }
@ -319,7 +319,7 @@ s32 sys_lwmutex_unlock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
const be_t<u32> tid = CPU.GetId(); const be_t<u32> tid = CPU.GetId();
// check owner // check owner
if (lwmutex->vars.owner.read_relaxed() != tid) if (lwmutex->vars.owner.load() != tid)
{ {
return CELL_EPERM; return CELL_EPERM;
} }
@ -392,7 +392,7 @@ s32 sys_lwcond_signal(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond)
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2); //return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2);
} }
if (lwmutex->vars.owner.read_relaxed() == CPU.GetId()) if (lwmutex->vars.owner.load() == CPU.GetId())
{ {
// if owns the mutex // if owns the mutex
lwmutex->all_info++; lwmutex->all_info++;
@ -450,7 +450,7 @@ s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond)
//return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2); //return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2);
} }
if (lwmutex->vars.owner.read_relaxed() == CPU.GetId()) if (lwmutex->vars.owner.load() == CPU.GetId())
{ {
// if owns the mutex, call the syscall // if owns the mutex, call the syscall
const s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1); const s32 res = _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 1);
@ -507,7 +507,7 @@ s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_t
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2); //return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2);
} }
if (lwmutex->vars.owner.read_relaxed() == CPU.GetId()) if (lwmutex->vars.owner.load() == CPU.GetId())
{ {
// if owns the mutex // if owns the mutex
lwmutex->all_info++; lwmutex->all_info++;
@ -561,7 +561,7 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
if (lwmutex->vars.owner.read_relaxed() != tid) if (lwmutex->vars.owner.load() != tid)
{ {
// if not owner of the mutex // if not owner of the mutex
return CELL_EPERM; return CELL_EPERM;
@ -1189,7 +1189,7 @@ void sys_spinlock_lock(vm::ptr<atomic_be_t<u32>> lock)
// prx: exchange with 0xabadcafe, repeat until exchanged with 0 // prx: exchange with 0xabadcafe, repeat until exchanged with 0
while (lock->exchange(0xabadcafe).data()) while (lock->exchange(0xabadcafe).data())
{ {
g_sys_spinlock_wm.wait_op(lock.addr(), [lock](){ return lock->read_relaxed().data() == 0; }); g_sys_spinlock_wm.wait_op(lock.addr(), [lock](){ return lock->load().data() == 0; });
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {

View file

@ -88,7 +88,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u64 intrthread,
return CELL_EAGAIN; return CELL_EAGAIN;
} }
if (s32 res = tag.assigned.atomic_op<s32>(CELL_OK, [](s32& value) -> s32 if (s32 res = tag.assigned.atomic_op([](s32& value) -> s32
{ {
if (value < 0) if (value < 0)
{ {
@ -113,7 +113,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u64 intrthread,
while (!Emu.IsStopped()) while (!Emu.IsStopped())
{ {
// call interrupt handler until int status is clear // call interrupt handler until int status is clear
if (tag.stat.read_relaxed()) if (tag.stat.load())
{ {
//func(CPU, arg); //func(CPU, arg);
CPU.GPR[3] = arg; CPU.GPR[3] = arg;

View file

@ -33,7 +33,7 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
const bool recursive = attr->recursive == SYS_SYNC_RECURSIVE; const bool recursive = attr->recursive == SYS_SYNC_RECURSIVE;
if ((!recursive && attr->recursive != SYS_SYNC_NOT_RECURSIVE) || attr->pshared.data() != SYS_SYNC_NOT_PROCESS_SHARED || attr->adaptive != SYS_SYNC_NOT_ADAPTIVE || attr->ipc_key.data() || attr->flags.data()) if ((!recursive && attr->recursive != SYS_SYNC_NOT_RECURSIVE) || attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->adaptive != SYS_SYNC_NOT_ADAPTIVE || attr->ipc_key.data() || attr->flags.data())
{ {
sys_mutex.Error("sys_mutex_create(): unknown attributes (recursive=0x%x, pshared=0x%x, adaptive=0x%x, ipc_key=0x%llx, flags=0x%x)", sys_mutex.Error("sys_mutex_create(): unknown attributes (recursive=0x%x, pshared=0x%x, adaptive=0x%x, ipc_key=0x%llx, flags=0x%x)",
attr->recursive, attr->pshared, attr->adaptive, attr->ipc_key, attr->flags); attr->recursive, attr->pshared, attr->adaptive, attr->ipc_key, attr->flags);

View file

@ -566,7 +566,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
{ {
auto& spu = static_cast<SPUThread&>(*t); auto& spu = static_cast<SPUThread&>(*t);
if (!(spu.status.read_relaxed() & SPU_STATUS_STOPPED_BY_STOP)) if (!(spu.status.load() & SPU_STATUS_STOPPED_BY_STOP))
{ {
stopped = false; stopped = false;
break; break;
@ -1253,7 +1253,7 @@ s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ptr<u64> mask)
auto& spu = static_cast<RawSPUThread&>(*t); auto& spu = static_cast<RawSPUThread&>(*t);
*mask = (class_id ? spu.int2 : spu.int0).mask.read_sync(); *mask = (class_id ? spu.int2 : spu.int0).mask.load();
return CELL_OK; return CELL_OK;
} }
@ -1299,7 +1299,7 @@ s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr<u64> stat)
auto& spu = static_cast<RawSPUThread&>(*t); auto& spu = static_cast<RawSPUThread&>(*t);
*stat = (class_id ? spu.int2 : spu.int0).stat.read_sync(); *stat = (class_id ? spu.int2 : spu.int0).stat.load();
return CELL_OK; return CELL_OK;
} }

View file

@ -333,7 +333,7 @@ void RSXDebugger::GoToGet(wxCommandEvent& event)
if (!RSXReady()) return; if (!RSXReady()) return;
auto ctrl = vm::get_ptr<CellGcmControl>(Emu.GetGSManager().GetRender().m_ctrlAddress); auto ctrl = vm::get_ptr<CellGcmControl>(Emu.GetGSManager().GetRender().m_ctrlAddress);
u32 realAddr; u32 realAddr;
if (Memory.RSXIOMem.getRealAddr(ctrl->get.read_relaxed(), realAddr)) { if (Memory.RSXIOMem.getRealAddr(ctrl->get.load(), realAddr)) {
m_addr = realAddr; m_addr = realAddr;
t_addr->SetValue(wxString::Format("%08x", m_addr)); t_addr->SetValue(wxString::Format("%08x", m_addr));
UpdateInformation(); UpdateInformation();
@ -347,7 +347,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event)
if (!RSXReady()) return; if (!RSXReady()) return;
auto ctrl = vm::get_ptr<CellGcmControl>(Emu.GetGSManager().GetRender().m_ctrlAddress); auto ctrl = vm::get_ptr<CellGcmControl>(Emu.GetGSManager().GetRender().m_ctrlAddress);
u32 realAddr; u32 realAddr;
if (Memory.RSXIOMem.getRealAddr(ctrl->put.read_relaxed(), realAddr)) { if (Memory.RSXIOMem.getRealAddr(ctrl->put.load(), realAddr)) {
m_addr = realAddr; m_addr = realAddr;
t_addr->SetValue(wxString::Format("%08x", m_addr)); t_addr->SetValue(wxString::Format("%08x", m_addr));
UpdateInformation(); UpdateInformation();

View file

@ -108,6 +108,8 @@ template<typename T> struct ID_type;
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big") #define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align) #define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
#define WRAP_EXPR(expr) [&]{ return (expr); }
#define _PRGNAME_ "RPCS3" #define _PRGNAME_ "RPCS3"
#define _PRGVER_ "0.0.0.5" #define _PRGVER_ "0.0.0.5"