mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
RawSPU: fix race condition in RunCntl stop request
This commit is contained in:
parent
ef6854ca46
commit
c11074a128
@ -8,6 +8,8 @@
|
||||
|
||||
inline void try_start(spu_thread& spu)
|
||||
{
|
||||
std::shared_lock lock(spu.run_ctrl_mtx);
|
||||
|
||||
if (spu.status_npc.fetch_op([](typename spu_thread::status_npc_sync_var& value)
|
||||
{
|
||||
if (value.status & SPU_STATUS_RUNNING)
|
||||
@ -246,8 +248,24 @@ bool spu_thread::write_reg(const u32 addr, const u32 value)
|
||||
}
|
||||
else if (value == SPU_RUNCNTL_STOP_REQUEST)
|
||||
{
|
||||
// TODO: Wait for the SPU to stop?
|
||||
state += cpu_flag::stop;
|
||||
if (get_current_cpu_thread() == this)
|
||||
{
|
||||
// TODO
|
||||
state += cpu_flag::stop;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::scoped_lock lock(run_ctrl_mtx);
|
||||
|
||||
if (status_npc.load().status & SPU_STATUS_RUNNING)
|
||||
{
|
||||
state += cpu_flag::stop;
|
||||
|
||||
for (status_npc_sync_var old; (old = status_npc).status & SPU_STATUS_RUNNING;)
|
||||
{
|
||||
status_npc.wait(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1096,19 +1096,22 @@ void spu_thread::cpu_stop()
|
||||
{
|
||||
if (!group && offset >= RAW_SPU_BASE_ADDR)
|
||||
{
|
||||
status_npc.fetch_op([this](status_npc_sync_var& state)
|
||||
if (status_npc.fetch_op([this](status_npc_sync_var& state)
|
||||
{
|
||||
if (state.status & SPU_STATUS_RUNNING)
|
||||
{
|
||||
// Save next PC and current SPU Interrupt Status
|
||||
// Used only by RunCtrl stop requests
|
||||
state.status &= ~SPU_STATUS_RUNNING;
|
||||
state.npc = pc | +interrupts_enabled;
|
||||
state.npc = pc | +interrupts_enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}).second)
|
||||
{
|
||||
status_npc.notify_one();
|
||||
}
|
||||
}
|
||||
else if (group && is_stopped())
|
||||
{
|
||||
@ -2842,6 +2845,8 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||
state.npc = (pc + 4) | +interrupts_enabled;
|
||||
});
|
||||
|
||||
status_npc.notify_one();
|
||||
|
||||
int_ctrl[2].set(SPU_INT2_STAT_SPU_STOP_AND_SIGNAL_INT);
|
||||
check_state();
|
||||
return true;
|
||||
@ -3196,6 +3201,8 @@ void spu_thread::halt()
|
||||
state.npc = pc | +interrupts_enabled;
|
||||
});
|
||||
|
||||
status_npc.notify_one();
|
||||
|
||||
int_ctrl[2].set(SPU_INT2_STAT_SPU_HALT_OR_STEP_INT);
|
||||
|
||||
spu_runtime::g_escape(this);
|
||||
|
@ -580,6 +580,7 @@ public:
|
||||
u32 ch_dec_value; // written decrementer value
|
||||
|
||||
atomic_t<u32> run_ctrl; // SPU Run Control register (only provided to get latest data written)
|
||||
shared_mutex run_ctrl_mtx;
|
||||
|
||||
struct alignas(8) status_npc_sync_var
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user