mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 21:38:01 +03:00
sys_mmapper: rewrite page fault thread notifications
* Fix a corner case where SPU thread has the same ID as a PPU thread. * Fix a potential deadlock on Emu.Stop() while sending event in EBUSY loop. * Thread specific notifications.
This commit is contained in:
parent
249686708c
commit
d86c9a2549
5 changed files with 39 additions and 31 deletions
|
@ -1442,13 +1442,19 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
|||
}
|
||||
}
|
||||
|
||||
// Deschedule
|
||||
if (cpu->id_type() == 1)
|
||||
{
|
||||
lv2_obj::sleep(*cpu);
|
||||
}
|
||||
|
||||
// Now, place the page fault event onto table so that other functions [sys_mmapper_free_address and pagefault recovery funcs etc]
|
||||
// know that this thread is page faulted and where.
|
||||
|
||||
auto pf_events = g_fxo->get<page_fault_event_entries>();
|
||||
{
|
||||
std::lock_guard pf_lock(pf_events->pf_mutex);
|
||||
pf_events->events.emplace(static_cast<u32>(data2), addr);
|
||||
pf_events->events.emplace(cpu, addr);
|
||||
}
|
||||
|
||||
sig_log.warning("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading",
|
||||
|
@ -1467,38 +1473,32 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
|||
// If we fail due to being busy, wait a bit and try again.
|
||||
while (static_cast<u32>(sending_error) == CELL_EBUSY)
|
||||
{
|
||||
if (cpu->id_type() == 1)
|
||||
if (cpu->is_stopped())
|
||||
{
|
||||
lv2_obj::sleep(*cpu, 1000);
|
||||
sending_error = {};
|
||||
break;
|
||||
}
|
||||
|
||||
thread_ctrl::wait_for(1000);
|
||||
sending_error = sys_event_port_send(pf_port_id, data1, data2, data3);
|
||||
}
|
||||
|
||||
if (cpu->id_type() == 1)
|
||||
{
|
||||
// Deschedule
|
||||
lv2_obj::sleep(*cpu);
|
||||
}
|
||||
|
||||
if (sending_error)
|
||||
{
|
||||
vm_log.fatal("Unknown error %x while trying to pass page fault.", +sending_error);
|
||||
cpu->state += cpu_flag::dbg_pause;
|
||||
vm_log.fatal("Unknown error 0x%x while trying to pass page fault.", +sending_error);
|
||||
}
|
||||
|
||||
// Wait until the thread is recovered
|
||||
for (std::shared_lock pf_lock(pf_events->pf_mutex);
|
||||
pf_events->events.count(static_cast<u32>(data2)) && !sending_error;)
|
||||
else
|
||||
{
|
||||
if (cpu->is_stopped())
|
||||
// Wait until the thread is recovered
|
||||
while (!cpu->state.test_and_reset(cpu_flag::signal))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (cpu->is_stopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Timeout in case the emulator is stopping
|
||||
pf_events->cond.wait(pf_lock, 10000);
|
||||
thread_ctrl::wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Reschedule, test cpu state and try recovery if stopped
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue