1
0
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:
Eladash 2020-02-19 22:25:53 +02:00 committed by Ivan
parent ef6854ca46
commit c11074a128
3 changed files with 31 additions and 5 deletions

View File

@ -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
{

View File

@ -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);

View File

@ -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
{