Correct when we process the stepping queue. Also, the jitLock mutex is no longer needed.

This commit is contained in:
Henrik Rydgård committed 2026-08-16 13:33:26 +02:00
1 parent 1848262bea
commit a49f4523cb
13 files changed
+18 -42

No files matched your search

+5 -5
View File
@@ -301,11 +301,6 @@ bool Core_GetPowerSaving() {
void Core_RunLoopUntil(u64 globalticks) { void Core_RunLoopUntil(u64 globalticks) {
while (true) { while (true) {
// Drain any functions queued up by Core_RunOnCPUThread() from other threads. Doing this at the
// top of this loop means it's reached at least once per call (i.e. about once per host frame)
// even while the CPU is fully running, and continuously (in a tight spin) while it's stepping/paused.
Core_ProcessCPUQueue();
switch (coreState) { switch (coreState) {
case CORE_POWERDOWN: case CORE_POWERDOWN:
case CORE_RUNTIME_ERROR: case CORE_RUNTIME_ERROR:
@@ -467,6 +462,11 @@ static void Core_PerformCPUStep(MIPSDebugInterface *cpu, CPUStepType stepType, i
static bool Core_ProcessStepping(MIPSDebugInterface *cpu) { static bool Core_ProcessStepping(MIPSDebugInterface *cpu) {
Core_StateProcessed(); Core_StateProcessed();
// Drain any functions queued up by Core_RunOnCPUThread() from other threads. Doing this at the
// top of this loop means it's reached at least once per call (i.e. about once per host frame)
// even while the CPU is fully running, and continuously (in a tight spin) while it's stepping/paused.
Core_ProcessCPUQueue();
// Check if there's any pending save state actions. // Check if there's any pending save state actions.
SaveState::Process(); SaveState::Process();
+2 -3
View File
@@ -73,10 +73,10 @@ static AutoDisabledReplacements LockMemory(bool keepReplacements) {
result.saved = true; result.saved = true;
// Okay, save so we can restore later. // Okay, save so we can restore later.
result.replacements = SaveAndClearReplacements(); result.replacements = SaveAndClearReplacements();
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock); if (MIPSComp::jit) {
if (MIPSComp::jit)
result.emuhacks = MIPSComp::jit->SaveAndClearEmuHackOps(); result.emuhacks = MIPSComp::jit->SaveAndClearEmuHackOps();
} }
}
return result; return result;
} }
@@ -91,7 +91,6 @@ AutoDisabledReplacements::AutoDisabledReplacements(AutoDisabledReplacements &&ot
AutoDisabledReplacements::~AutoDisabledReplacements() { AutoDisabledReplacements::~AutoDisabledReplacements() {
if (saved) { if (saved) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) if (MIPSComp::jit)
MIPSComp::jit->RestoreSavedEmuHackOps(emuhacks); MIPSComp::jit->RestoreSavedEmuHackOps(emuhacks);
RestoreSavedReplacements(replacements); RestoreSavedReplacements(replacements);
+1 -4
View File
@@ -57,7 +57,6 @@
namespace MIPSComp { namespace MIPSComp {
JitInterface *jit; JitInterface *jit;
std::recursive_mutex jitLock;
void JitAt() { void JitAt() {
// TODO: We could probably check for a bad pc here, and fire an exception. Could spare us from some crashes. // TODO: We could probably check for a bad pc here, and fire an exception. Could spare us from some crashes.
@@ -185,7 +184,6 @@ std::string AddAddress(const std::string &buf, uint64_t addr) {
#if PPSSPP_ARCH(ARM64) || defined(DISASM_ALL) #if PPSSPP_ARCH(ARM64) || defined(DISASM_ALL)
static bool Arm64SymbolCallback(char *buffer, int bufsize, uint8_t *address) { static bool Arm64SymbolCallback(char *buffer, int bufsize, uint8_t *address) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
std::string name; std::string name;
if (MIPSComp::jit->DescribeCodePtr(address, name)) { if (MIPSComp::jit->DescribeCodePtr(address, name)) {
@@ -275,11 +273,10 @@ const char *ppsspp_resolver(struct ud*,
// But these do. // But these do.
// UGLY HACK because the API is terrible // UGLY HACK because the disassembler API is terrible
static char buf[128]; static char buf[128];
std::string str; std::string str;
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr((u8 *)(uintptr_t)addr, str)) { if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr((u8 *)(uintptr_t)addr, str)) {
*offset = 0; *offset = 0;
truncate_cpy(buf, sizeof(buf), str); truncate_cpy(buf, sizeof(buf), str);
-2
View File
@@ -17,7 +17,6 @@
#pragma once #pragma once
#include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -170,7 +169,6 @@ namespace MIPSComp {
u32 ResolveNotTakenTarget(const BranchInfo &branchInfo); u32 ResolveNotTakenTarget(const BranchInfo &branchInfo);
extern JitInterface *jit; extern JitInterface *jit;
extern std::recursive_mutex jitLock;
void DoDummyJitState(PointerWrap &p); void DoDummyJitState(PointerWrap &p);
-9
View File
@@ -161,7 +161,6 @@ MIPSState::~MIPSState() {
} }
void MIPSState::Shutdown() { void MIPSState::Shutdown() {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
MIPSComp::JitInterface *oldjit = MIPSComp::jit; MIPSComp::JitInterface *oldjit = MIPSComp::jit;
if (oldjit) { if (oldjit) {
MIPSComp::jit = nullptr; MIPSComp::jit = nullptr;
@@ -209,7 +208,6 @@ void MIPSState::Init() {
memset(vcmpResult, 0, sizeof(vcmpResult)); memset(vcmpResult, 0, sizeof(vcmpResult));
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (PSP_CoreParameter().cpuCore == CPUCore::JIT || PSP_CoreParameter().cpuCore == CPUCore::JIT_IR) { if (PSP_CoreParameter().cpuCore == CPUCore::JIT || PSP_CoreParameter().cpuCore == CPUCore::JIT_IR) {
MIPSComp::jit = MIPSComp::CreateNativeJit(this, PSP_CoreParameter().cpuCore == CPUCore::JIT_IR); MIPSComp::jit = MIPSComp::CreateNativeJit(this, PSP_CoreParameter().cpuCore == CPUCore::JIT_IR);
} else if (PSP_CoreParameter().cpuCore == CPUCore::IR_INTERPRETER) { } else if (PSP_CoreParameter().cpuCore == CPUCore::IR_INTERPRETER) {
@@ -231,13 +229,10 @@ void MIPSState::UpdateCore(CPUCore desired) {
IncrementDebugCounter(DebugCounter::CPUCORE_SWITCHES); IncrementDebugCounter(DebugCounter::CPUCORE_SWITCHES);
// Get rid of the old JIT first, before switching. // Get rid of the old JIT first, before switching.
{
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
delete MIPSComp::jit; delete MIPSComp::jit;
MIPSComp::jit = nullptr; MIPSComp::jit = nullptr;
} }
}
PSP_CoreParameter().cpuCore = desired; PSP_CoreParameter().cpuCore = desired;
@@ -264,7 +259,6 @@ void MIPSState::UpdateCore(CPUCore desired) {
break; break;
} }
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
MIPSComp::jit = newjit; MIPSComp::jit = newjit;
} }
@@ -356,7 +350,6 @@ int MIPSState::RunLoopUntil(u64 globalTicks) {
static std::vector<std::pair<u32, int>> pendingClears; static std::vector<std::pair<u32, int>> pendingClears;
void MIPSState::ProcessPendingClears() { void MIPSState::ProcessPendingClears() {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
for (auto &p : pendingClears) { for (auto &p : pendingClears) {
if (p.first == 0 && p.second == 0) if (p.first == 0 && p.second == 0)
MIPSComp::jit->ClearCache(); MIPSComp::jit->ClearCache();
@@ -370,14 +363,12 @@ void MIPSState::ProcessPendingClears() {
void MIPSState::InvalidateICache(u32 address, int length) { void MIPSState::InvalidateICache(u32 address, int length) {
// Only really applies to jit. // Only really applies to jit.
// Note that the backend is responsible for ensuring native code can still be returned to. // Note that the backend is responsible for ensuring native code can still be returned to.
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit && length != 0) { if (MIPSComp::jit && length != 0) {
MIPSComp::jit->InvalidateCacheAt(address, length); MIPSComp::jit->InvalidateCacheAt(address, length);
} }
} }
void MIPSState::ClearJitCache() { void MIPSState::ClearJitCache() {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
if (coreState == CORE_RUNNING_CPU || insideJit) { if (coreState == CORE_RUNNING_CPU || insideJit) {
pendingClears.emplace_back(0, 0); pendingClears.emplace_back(0, 0);
-3
View File
@@ -19,7 +19,6 @@
#include <cstdint> #include <cstdint>
#include <unordered_set> #include <unordered_set>
#include <mutex>
#include <sstream> #include <sstream>
#include "Common/StringUtils.h" #include "Common/StringUtils.h"
@@ -121,8 +120,6 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
SContext *context = (SContext *)ctx; SContext *context = (SContext *)ctx;
const uint8_t *codePtr = (uint8_t *)(context->CTX_PC); const uint8_t *codePtr = (uint8_t *)(context->CTX_PC);
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
// We set this later if we think it can be resumed from. // We set this later if we think it can be resumed from.
g_lastCrashAddress = nullptr; g_lastCrashAddress = nullptr;
-1
View File
@@ -165,7 +165,6 @@ int g_screenshotFailures;
// These must be saved before copying out memory and restored after. // These must be saved before copying out memory and restored after.
auto savedReplacements = SaveAndClearReplacements(); auto savedReplacements = SaveAndClearReplacements();
if (MIPSComp::jit && p.mode == p.MODE_WRITE) { if (MIPSComp::jit && p.mode == p.MODE_WRITE) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
std::vector<u32> savedBlocks; std::vector<u32> savedBlocks;
savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps(); savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps();
-2
View File
@@ -359,7 +359,6 @@ void CwCheatScreen::onFinish(DialogResult result) {
if (result != DR_BACK) // This only works for BACK here. if (result != DR_BACK) // This only works for BACK here.
return; return;
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
MIPSComp::jit->ClearCache(); MIPSComp::jit->ClearCache();
} }
@@ -385,7 +384,6 @@ void CwCheatScreen::OnAddCheat(UI::EventParams &params) {
void CwCheatScreen::OnEditCheatFile(UI::EventParams &params) { void CwCheatScreen::OnEditCheatFile(UI::EventParams &params) {
g_Config.bReloadCheats = true; g_Config.bReloadCheats = true;
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
MIPSComp::jit->ClearCache(); MIPSComp::jit->ClearCache();
} }
-2
View File
@@ -337,7 +337,6 @@ void JitCompareScreen::OnBlockClick(UI::EventParams &e) {
} }
void JitCompareScreen::OnAddressChange(UI::EventParams &e) { void JitCompareScreen::OnAddressChange(UI::EventParams &e) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (!MIPSComp::jit) { if (!MIPSComp::jit) {
return; return;
} }
@@ -364,7 +363,6 @@ void JitCompareScreen::OnSelectBlock(UI::EventParams &e) {
} }
void JitCompareScreen::OnBlockAddress(UI::EventParams &e) { void JitCompareScreen::OnBlockAddress(UI::EventParams &e) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (!MIPSComp::jit) { if (!MIPSComp::jit) {
return; return;
} }
-1
View File
@@ -67,7 +67,6 @@ void HandleCommonMessages(UIMessage message, const char *value, ScreenManager *m
if (message == UIMessage::REQUEST_CLEAR_JIT && PSP_IsInited()) { if (message == UIMessage::REQUEST_CLEAR_JIT && PSP_IsInited()) {
// TODO: This seems to clearly be the wrong place to handle this. // TODO: This seems to clearly be the wrong place to handle this.
if (MIPSComp::jit) { if (MIPSComp::jit) {
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) if (MIPSComp::jit)
MIPSComp::jit->ClearCache(); MIPSComp::jit->ClearCache();
} }
+3 -5
View File
@@ -1280,12 +1280,10 @@ void NativeFrame(GraphicsContext *graphicsContext) {
g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation);
// Drain any work queued by Core_RunOnCPUThread() from other threads. Core_RunLoopUntil() if (GetUIState() != UISTATE_INGAME) {
// (called from within render() below, but only while a game is actually loaded/running) // In case there are any cross thread requests outside the game.
// also does this, but that path isn't reached at all outside a game - e.g. from the main
// menu - so queued work would otherwise hang forever waiting for it. See Core_ProcessCPUQueue()
// in Core.h.
Core_ProcessCPUQueue(); Core_ProcessCPUQueue();
}
// All actual rendering (and also emulation) happens in this render() call. // All actual rendering (and also emulation) happens in this render() call.
renderFlags = g_screenManager->Render([]() { renderFlags = g_screenManager->Render([]() {
-1
View File
@@ -102,7 +102,6 @@ INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam,
fwrite(Memory::GetPointerOrException(bp->start), 1, bp->size, output); fwrite(Memory::GetPointerOrException(bp->start), 1, bp->size, output);
} else { } else {
auto savedReplacements = SaveAndClearReplacements(); auto savedReplacements = SaveAndClearReplacements();
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit) { if (MIPSComp::jit) {
auto savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps(); auto savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps();
fwrite(Memory::GetPointerOrException(bp->start), 1, bp->size, output); fwrite(Memory::GetPointerOrException(bp->start), 1, bp->size, output);
+7 -4
View File
@@ -1018,21 +1018,24 @@ namespace MainWindow {
case VERYSLEEPY_WPARAM_GETADDRINFO: case VERYSLEEPY_WPARAM_GETADDRINFO:
{ {
Core_RunOnCPUThread([lParam]() {
// This is called from VerySleepy, which is on a different thread than the CPU thread.
// We need to run this on the CPU thread to avoid race conditions.
VerySleepy_AddrInfo *info = (VerySleepy_AddrInfo *)lParam; VerySleepy_AddrInfo *info = (VerySleepy_AddrInfo *)lParam;
const u8 *ptr = (const u8 *)info->addr; const u8 *ptr = (const u8 *)info->addr;
std::string name; std::string name;
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) { if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) {
swprintf_s(info->name, L"Jit::%S", name.c_str()); swprintf_s(info->name, L"Jit::%S", name.c_str());
return TRUE; return;
} }
if (gpu && gpu->DescribeCodePtr(ptr, name)) { if (gpu && gpu->DescribeCodePtr(ptr, name)) {
swprintf_s(info->name, L"GPU::%S", name.c_str()); swprintf_s(info->name, L"GPU::%S", name.c_str());
return;
}
});
return TRUE; return TRUE;
} }
}
return FALSE;
default: default:
return FALSE; return FALSE;