mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Queue CPU step requests instead of rejecting all but the first
Only one step can be carried out per pass through Core_ProcessStepping(), so roughly one per host frame. A second request arriving before that was rejected outright - "Can't submit two steps in one host frame" - with no step performed, which put the burden on every caller to notice and retry. A script firing five cpu.stepInto in a row advanced one instruction and logged four errors. They queue now, up to 8 deep; past that something is looping and it says so rather than growing without bound. Five stepIntos advance five instructions. The queue is deliberately *not* cleared by Core_Break(). That looks like the obvious place for it - stopping for another reason should abandon a pending plan, the way the temporary breakpoint and the runUntilTime deadline are dropped there - but completing a step-over or step-out goes *through* Core_Break(), since their temporary breakpoint is what stops us. Clearing there would throw away everything after the first entry of any sequence. It's cleared on CoreLifecycle::STARTING instead, so a step queued against the game that just went away can't run against the new one. g_cpuStepCommand keeps its existing double duty as both "the step in flight" and "why we're stopped" (reason/relatedAddr, read by Core_GetSteppingReason), so Core_Break()'s override check for an in-progress Over/Out is unchanged. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
This commit is contained in:
1 parent
d72623c4a0
commit
c0545658bc
2 files changed
+39
-11
No files matched your search
@@ -87,8 +87,8 @@ static DebugInterface *CPUFromRequest(DebuggerRequest &req, uint32_t *threadID =
|
||||
//
|
||||
// Response (same event name) with no extra data on success. A cpu.stepping event follows once
|
||||
// the step completes.
|
||||
// May fail (same-thread case only) if another step/run request is already pending this host
|
||||
// frame - safe to retry shortly after.
|
||||
// May fail (same-thread case only) if too many steps are already queued, which means a client is
|
||||
// firing them faster than they can possibly be carried out.
|
||||
//
|
||||
// Note: any thread can wake the cpu when it hits the next instruction currently.
|
||||
void WebSocketSteppingState::Into(DebuggerRequest &req) {
|
||||
@@ -114,11 +114,10 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) {
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
g_breakpoints.SetSkipFirst(currentMIPS->pc);
|
||||
|
||||
// Core_RequestCPUStep() can fail (a step or run request is already queued this host
|
||||
// frame - see its own "Can't submit two steps in one host frame" log). On failure no
|
||||
// step ever happens and no cpu.stepping event ever fires, so a rejected step would
|
||||
// otherwise be indistinguishable from one still in flight - the acknowledgement every
|
||||
// request now gets doesn't tell those apart. Surface it as an error instead.
|
||||
// Steps queue up now, so this only fails once the queue is full - a client stepping
|
||||
// far faster than frames go by. No step happens and no cpu.stepping event fires in
|
||||
// that case, which would otherwise be indistinguishable from one still in flight, so
|
||||
// surface it as an error rather than leaving the caller waiting.
|
||||
if (!Core_RequestCPUStep(CPUStepType::Into)) {
|
||||
req.Fail("Could not step: a step or run request is already pending");
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user