From 300701a06be7ec3d6f1d23539ec0db57b3256f81 Mon Sep 17 00:00:00 2001 From: Eladash Date: Fri, 19 May 2023 21:52:57 +0300 Subject: [PATCH] Make page faults entry enqueue and event atomic --- Utilities/Thread.cpp | 37 ++++++++++++++++++++---------- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 16 ++++++++----- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 0ad97940c6..05379c5b88 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -4,6 +4,7 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/lv2/sys_mmapper.h" #include "Emu/Cell/lv2/sys_event.h" +#include "Emu/Cell/lv2/sys_process.h" #include "Emu/RSX/RSXThread.h" #include "Thread.h" #include "Utilities/JIT.h" @@ -1514,7 +1515,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe } } - if (pf_port_id) + if (auto pf_port = idm::get(pf_port_id); pf_port && pf_port->queue) { // We notify the game that a page fault occurred so it can rectify it. // Note, for data3, were the memory readable AND we got a page fault, it must be due to a write violation since reads are allowed. @@ -1552,21 +1553,34 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe } } - // 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(); + + // De-schedule + if (cpu->id_type() == 1) { - std::lock_guard pf_lock(pf_events.pf_mutex); - pf_events.events.emplace(cpu, addr); + cpu->state -= cpu_flag::signal; // Cannot use check_state here and signal must be removed if exists + lv2_obj::sleep(*cpu); } + auto send_event = [&]() -> error_code + { + lv2_obj::notify_all_t notify_later{}; + + std::lock_guard pf_lock(pf_events.pf_mutex); + + if (auto error = pf_port->queue->send(pf_port->name ? pf_port->name : ((u64{process_getpid() + 0u} << 32) | u64{pf_port_id}), data1, data2, data3)) + { + return error; + } + + pf_events.events.emplace(cpu, addr); + return {}; + }; + sig_log.warning("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading", addr, data3 == SYS_MEMORY_PAGE_FAULT_CAUSE_READ_ONLY ? "writing read-only" : "using unmapped"); @@ -1578,13 +1592,12 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe } } - error_code sending_error = sys_event_port_send(pf_port_id, data1, data2, data3); + error_code sending_error = not_an_error(CELL_EBUSY); // If we fail due to being busy, wait a bit and try again. - while (static_cast(sending_error) == CELL_EBUSY) + for (; static_cast(sending_error) == CELL_EBUSY; thread_ctrl::wait_for(1000)) { - thread_ctrl::wait_for(1000); - sending_error = sys_event_port_send(pf_port_id, data1, data2, data3); + sending_error = send_event(); if (cpu->is_stopped()) { diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index f16f102674..69eeef1273 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -846,15 +846,19 @@ error_code mmapper_thread_recover_page_fault(cpu_thread* cpu) } pf_events.events.erase(pf_event_ind); + + if (cpu->id_type() == 1u) + { + lv2_obj::awake(cpu); + } + else + { + cpu->state += cpu_flag::signal; + } } - if (cpu->id_type() == 1u) + if (cpu->state & cpu_flag::signal) { - lv2_obj::awake(cpu); - } - else - { - cpu->state += cpu_flag::signal; cpu->state.notify_one(cpu_flag::signal); }