rsx: Avoid potential deadlock in FIFO_ctrl

This commit is contained in:
kd-11 2019-01-15 15:37:26 +03:00 committed by kd-11
parent 7eec702c6d
commit 10a17feda2
2 changed files with 22 additions and 21 deletions

View file

@ -19,22 +19,22 @@ namespace rsx
m_ctrl = pctrl->ctrl; m_ctrl = pctrl->ctrl;
} }
void FIFO_control::inc_get() void FIFO_control::inc_get(bool wait)
{ {
m_internal_get += 4; m_internal_get += 4;
// Check if put allows to procceed execution if (wait && m_ctrl->put == m_internal_get)
while (m_ctrl->put == m_internal_get)
{ {
if (Emu.IsStopped()) // NOTE: Only supposed to be invoked to wait for a single arg on command[0] (4 bytes)
{ // Wait for put to allow us to procceed execution
break;
}
sync_get(); sync_get();
while (m_ctrl->put == m_internal_get && !Emu.IsStopped())
{
std::this_thread::yield(); std::this_thread::yield();
} }
} }
}
void FIFO_control::set_put(u32 put) void FIFO_control::set_put(u32 put)
{ {
@ -62,6 +62,7 @@ namespace rsx
// Update ctrl registers // Update ctrl registers
m_ctrl->get = get; m_ctrl->get = get;
m_internal_get = get; m_internal_get = get;
m_remaining_commands = 0;
// Clear memwatch spinner // Clear memwatch spinner
m_memwatch_addr = 0; m_memwatch_addr = 0;
@ -70,19 +71,13 @@ namespace rsx
bool FIFO_control::read_unsafe(register_pair& data) bool FIFO_control::read_unsafe(register_pair& data)
{ {
// Fast read with no processing, only safe inside a PACKET_BEGIN+count block // Fast read with no processing, only safe inside a PACKET_BEGIN+count block
if (m_remaining_commands) if (m_remaining_commands &&
m_internal_get != m_ctrl->put)
{ {
m_command_reg += m_command_inc; m_command_reg += m_command_inc;
m_args_ptr += 4; m_args_ptr += 4;
m_remaining_commands--;
if (--m_remaining_commands)
{
inc_get();
}
else
{
m_internal_get += 4; m_internal_get += 4;
}
data.set(m_command_reg, vm::read32(m_args_ptr)); data.set(m_command_reg, vm::read32(m_args_ptr));
return true; return true;
@ -103,6 +98,12 @@ namespace rsx
return; return;
} }
if (m_remaining_commands && read_unsafe(data))
{
// Previous block aborted to wait for PUT pointer
return;
}
if (m_memwatch_addr) if (m_memwatch_addr)
{ {
if (m_internal_get == m_memwatch_addr) if (m_internal_get == m_memwatch_addr)
@ -179,7 +180,7 @@ namespace rsx
m_remaining_commands = count - 1; m_remaining_commands = count - 1;
} }
inc_get(); inc_get(true); // Wait for data block to become available
m_internal_get += 4; m_internal_get += 4;
data.set(cmd & 0xfffc, vm::read32(m_args_ptr)); data.set(cmd & 0xfffc, vm::read32(m_args_ptr));

View file

@ -115,7 +115,7 @@ namespace rsx
u32 get_pos() { return m_internal_get; } u32 get_pos() { return m_internal_get; }
void sync_get() { m_ctrl->get.store(m_internal_get); } void sync_get() { m_ctrl->get.store(m_internal_get); }
void inc_get(); void inc_get(bool wait);
void set_get(u32 get); void set_get(u32 get);
void set_put(u32 put); void set_put(u32 put);