mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 01:59:34 +01:00
Debugger: Route cpu.stepInto's stepping state through the CPU thread
The WebSocket debugger's cpu.stepInto handler ran entirely on the WebSocket handler thread, directly manipulating breakpoints and stepping state (via Core_RequestCPUStep, g_breakpoints.SetSkipFirst, etc.) that's otherwise only ever touched from the CPU thread (the one that calls Core_RunLoopUntil, and thus indirectly NativeFrame). Adds Core_RunOnCPUThread() - queues a function to run on the CPU thread and blocks the caller until it's done. The queue is drained at the top of Core_RunLoopUntil()'s loop, so it's reached continuously (in a tight spin) while the CPU is stepping/paused, and at least once per call even while fully running. cpu.stepInto is the first consumer: once the CPU is already stepping, the breakpoint/stepping manipulation is now routed through Core_RunOnCPUThread instead of happening directly on the WebSocket thread. The "not currently stepping" path still calls Core_Break() directly from the WebSocket thread, since it's already documented free-threaded and is what makes the CPU thread start reaching the queue-drain point in the first place. More WebSocket debugger commands can be converted the same way going forward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
This commit is contained in:
1 parent
b1f0112cef
commit
c6fccefa49
3 files changed
+108
-19
No files matched your search
@@ -89,32 +89,40 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) {
|
||||
if (!currentDebugMIPS->isAlive())
|
||||
return req.Fail("CPU not started");
|
||||
if (!Core_IsStepping()) {
|
||||
// Core_Break() is explicitly free-threaded (see Core.cpp), so no need to bounce this to the CPU
|
||||
// thread - and we can't anyway, since Core_RunOnCPUThread() is only drained once the CPU actually
|
||||
// *is* stepping, which this call is what triggers in the first place.
|
||||
Core_Break(BreakReason::DebugStepInto, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t threadID;
|
||||
auto cpuDebug = CPUFromRequest(req, &threadID);
|
||||
if (!cpuDebug)
|
||||
return;
|
||||
// The CPU is already stepping/paused, so the CPU thread is spinning in Core_ProcessStepping() and will
|
||||
// promptly drain this. Route the actual breakpoint/stepping manipulation there instead of poking at it
|
||||
// directly from this WebSocket handler thread.
|
||||
Core_RunOnCPUThread([&] {
|
||||
uint32_t threadID;
|
||||
auto cpuDebug = CPUFromRequest(req, &threadID);
|
||||
if (!cpuDebug)
|
||||
return;
|
||||
|
||||
if (cpuDebug == currentDebugMIPS) {
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
g_breakpoints.SetSkipFirst(currentMIPS->pc);
|
||||
if (cpuDebug == currentDebugMIPS) {
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
g_breakpoints.SetSkipFirst(currentMIPS->pc);
|
||||
|
||||
Core_RequestCPUStep(CPUStepType::Into, 1);
|
||||
} else {
|
||||
uint32_t breakpointAddress = cpuDebug->GetPC();
|
||||
PrepareResume();
|
||||
// Could have advanced to the breakpoint already in PrepareResume().
|
||||
// Note: we need to get cpuDebug again anyway (in case we ran some HLE above.)
|
||||
cpuDebug = CPUFromRequest(req);
|
||||
if (cpuDebug != currentDebugMIPS) {
|
||||
g_breakpoints.AddBreakPoint(breakpointAddress, true);
|
||||
AddThreadCondition(breakpointAddress, threadID);
|
||||
Core_Resume();
|
||||
Core_RequestCPUStep(CPUStepType::Into, 1);
|
||||
} else {
|
||||
uint32_t breakpointAddress = cpuDebug->GetPC();
|
||||
PrepareResume();
|
||||
// Could have advanced to the breakpoint already in PrepareResume().
|
||||
// Note: we need to get cpuDebug again anyway (in case we ran some HLE above.)
|
||||
cpuDebug = CPUFromRequest(req);
|
||||
if (cpuDebug != currentDebugMIPS) {
|
||||
g_breakpoints.AddBreakPoint(breakpointAddress, true);
|
||||
AddThreadCondition(breakpointAddress, threadID);
|
||||
Core_Resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Step over the next instruction (cpu.stepOver)
|
||||
|
||||
Reference in new issue
Block a user