Repository navigation
Hot Path vCPU Recognized Poll Loop Wait
Lifecycle: Performance - Unproven · Type: Guest-execution shortcut
State: Source-backed; runtime value is not established.
Status: Conditionally applicable, high-risk research candidate; not implemented and not benchmarked.
Mechanism class: Guarded shortcut / guest-execution bypass.
Reviewed source:
322986f4c5502b3fa887a9605ac8cd88e9b2c579Subsystem: vCPU/TCG and selected device completion events.
The existing PGRAPH fence shortcut removes pgraph.lock from one exact busy-polled register read. It does not remove the guest load/compare/branch loop around that read. A recognized poll-loop shortcut would detect one proven side-effect-free wait loop, sleep the vCPU until the producer changes the relevant condition or another wake reason occurs, then retry the original guest instructions.
This can remove thousands of guest instructions and MMIO reads, but it is much riskier than making one register access cheaper. Generic spin-loop recognition is not acceptable. The first implementation must target one profiled loop and one explicit device event.
flowchart TD
A[Guest enters fence/status polling loop] --> B[Translated load]
B --> C[MMIO/device read]
C --> D[Guest compare and branch]
D -->|Condition false| B
D -->|Condition true| E[Guest continues]
F[Producer updates completion state] --> C
With the current fence-read fast path, the MMIO read may avoid a mutex, but the vCPU still executes each loop iteration.
sequenceDiagram
participant CPU as vCPU / recognized TB
participant Dev as Device producer
participant Wait as Event/sequence wait
CPU->>CPU: Validate exact loop plan and side-effect-free state
CPU->>Dev: Read condition and producer sequence
CPU->>CPU: Condition still false?
alt condition false
CPU->>Wait: Register wait using observed sequence
Dev->>Dev: Publish completion/state
Dev->>Wait: Signal and advance sequence
Wait-->>CPU: Wake on device, interrupt, timer, stop or deadline
CPU->>CPU: Retry original guest loop
else condition true
CPU->>CPU: Execute original exit path
end
The original loop must execute again after waking. The shortcut does not fabricate final flags, counters, instruction pointer state, or timeout results.
A plan must bind to a validated translated-code region and include at least:
- guest PC range and code identity/hash;
- the exact load address/register width;
- comparison and branch condition;
- proof that the loop body has no other memory/device side effects;
- proof that it does not update a guest counter or timeout state;
- the producer event/sequence that can make progress;
- interrupt, timer, reset, stop, and snapshot wake conditions;
- invalidation when guest code or mapping changes.
A loop that merely resembles a known pattern is not enough.
The basic wait must follow a sequence protocol:
1. Read producer sequence.
2. Re-read the guest-visible condition.
3. If complete, run the original loop normally.
4. Register/sleep only if the sequence still matches.
5. Producer updates state, advances the sequence, and signals.
6. Wake and retry original guest code.
The wait must handle completion immediately before registration, during registration, and immediately after sleep begins. A plain “check then sleep” is incorrect.
The vCPU must wake for more than the target device event:
- target condition publication;
- pending guest interrupt or NMI;
- timer/deadline expiration;
- VM stop/pause/shutdown/reset;
- debugger/watchpoint activity;
- snapshot/load transition;
- TLB/TB invalidation or self-modifying code;
- spurious wakeup;
- safety watchdog for a producer that never completes.
After any wake, the original loop determines whether it exits.
The guest observes instruction effects, interrupt timing, timeout behavior, and device completion—not the host CPU cycles spent polling.
The equivalent contract is narrow:
For an admitted loop, replacing repeated iterations with a wait must produce the same observable loop exit, interrupt recognition, timeout behavior, and device ordering as executing those iterations normally.
If the shortcut intentionally removes a guest timeout or counter update, it is an approximation and must be classified separately.
Potential benefit:
recognized loop iterations avoided
× translated instruction and MMIO cost per iteration
− recognition, registration and wake cost
It can reduce vCPU CPU time even when guest completion latency does not change. That can still be valuable if the freed host core improves other threads or power use.
Current source explicitly says the Xbox D3D runtime busy-polls NV_PGRAPH_PATT_COLOR0. The existing narrow fast path confirms one important polling target and ordered producer publication.
No current source evidence identifies the exact guest instruction loops, their timeout behavior, or their side effects. A Release trace plus guest disassembly is required before creating a recognizer.
| Area | Role |
|---|---|
hw/xbox/nv2a/pgraph/pgraph.c |
Current exact fence register fast read and producer ordering contract |
| x86 translator / TCG TB metadata | Candidate loop identification and invalidation |
| vCPU execution/exit path | Sleep, wake, interrupt/deadline handling and retry |
| PGRAPH/PFIFO producer | Completion sequence publication and signal |
| snapshot/reset/debug paths | Cancel waits and invalidate plans |
- identify the exact hot guest PCs and loop forms;
- count iterations and MMIO reads;
- resolve whether the loop includes timeout/counter side effects;
- map the producer event that changes the condition.
Use one title/build/loop signature with a non-persistent switch. The goal is to test the scheduling and wake contract, not create a general optimizer.
Only after the diagnostic succeeds should the design support code identity, mapping epochs, sequence publication, and invalidation as first-class data.
- Signal completion before, during, and after registration.
- Inject spurious wakeups.
- Leave the producer incomplete and require timer/interrupt progress.
- Add a guest counter increment inside the loop; recognition must fail.
- Add a read from a side-effecting register; recognition must fail.
- Add timeout arithmetic; recognition must fail unless modeled exactly.
- Modify the guest code after translation; the plan must invalidate.
- Remap the polled address.
- Restore a snapshot while the vCPU is asleep.
- Trigger an interrupt that the original loop would recognize.
poll_plan_candidates
poll_plan_admitted
poll_plan_rejected_by_reason
poll_wait_entries
poll_wait_wakes_device
poll_wait_wakes_interrupt
poll_wait_wakes_timer
poll_wait_spurious
poll_wait_timeouts
poll_iterations_avoided
mmio_reads_avoided
vcpu_cpu_ns
producer_completion_latency
false_recognition_failures
- Lost wakeup and permanent hang.
- Delayed or missed interrupt recognition.
- Skipping guest timeout/counter behavior.
- False recognition of a loop with side effects.
- Self-modifying code or mapping changes leaving a stale plan.
- Deadlock if the producer requires work from the sleeping vCPU or BQL owner.
- Better host CPU usage but worse guest latency.
- Title/build signatures becoming brittle maintenance hacks.
- Capture optimized Release + matching DWARF evidence for the target loop.
- Publish guest disassembly and exact loop semantics.
- Build deterministic lost-wakeup, interrupt, timeout, side-effect, SMC, restore, and deadlock tests.
- Keep the normal guest loop as the maintained reference route.
- Run same-binary route A/B with effective-state and wake counters.
- Compare vCPU CPU, producer latency, guest progress, p95/p99, and correctness.
- Limit any initial product exposure to the exact proven pattern.
- Reject generic recognition until multiple independently proven loops share one safe contract.
Conditionally applicable and potentially hard-hitting, but only after identifying a specific loop. The source supports the fence-poll motivation; it does not support a generic spin-loop bypass today.
- Fast GPU Fence Polling
- CPU & vCPU Execution
- Debugging Lag & Hot-Path Analysis
- Assumption-Based Shortcut Validation
Primary reference: This subject page is the design and research reference for Recognized Poll-Loop Wait. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Guest-execution bypass with event wake
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579· Acceptance class: intended exact or behavior-preserving for its admitted scope
Recognize one exact side-effect-free guest polling loop and sleep the vCPU until the producing emulated event, interrupt, timer, invalidation, or deadline requires retrying the original loop.
This entry remains Unproven: the source path and opportunity are concrete, but no accepted xemu runtime result has established that the candidate improves representative workloads. The page defines what must be bypassed, what remains mandatory, and how the hypothesis can be rejected.
| File / function | Role |
|---|---|
hw/xbox/nv2a/pgraph/* |
guest-polled PGRAPH register and producer event |
target/i386/tcg/translate.c |
loop translation/code identity |
accel/tcg/* |
vCPU wait, interrupt and TB invalidation boundaries |
flowchart TD
N0["Guest load MMIO/status"]
N1["Compare"]
N0 --> N1
N2["Conditional branch back"]
N1 --> N2
N3["Repeat many iterations"]
N2 --> N3
N4["Eventually observe producer change"]
N3 --> N4
flowchart TD
N0["Validate exact loop plan"]
N1["Check condition and producer sequence"]
N0 --> N1
N2["Register wait without lost wake"]
N1 --> N2
N3["Sleep vCPU"]
N2 --> N3
N4["Wake on event/interrupt/timer/invalidation"]
N3 --> N4
N5["Retry original guest loop"]
N4 --> N5
Making each polled read cheaper still leaves the guest executing load/compare/branch. A proven wait loop can remove many iterations, but generic spin-loop recognition is unsafe because loops may contain timeout arithmetic, counters, side-effecting reads, or rely on interrupt timing.
- Repeated guest instructions
- Repeated MMIO/status reads
- TB dispatch/chaining for the loop
- Host CPU busy time while producer is pending
- Final original load/compare/exit semantics
- Interrupt/timer recognition
- Producer progress
- Timeout behavior if present
- Reference execution on any uncertainty
uint64_t seq = producer_sequence(plan->producer);
if (!poll_condition_satisfied(plan) &&
validate_poll_loop_code(plan) &&
register_waiter_if_sequence_unchanged(plan, seq)) {
cpu_wait_until_event_or_exit(cpu, plan->deadline);
return RETRY_ORIGINAL_GUEST_LOOP;
}
return EXECUTE_REFERENCE_LOOP;The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.
- Recognition binds exact guest PC/code bytes, MMIO read width/address, compare and branch, with no side effects.
- Producer sequence handshake prevents lost wakeups.
- Interrupts, timers, stop/reset, self-modifying code and remap invalidate/wake.
- On wake, original code rechecks the condition.
The plan is attached to translated-code identity and one producer event. TB invalidation/self-modification removes it. Wait registration is synchronized with the producer sequence. Snapshot/reset cancels waiters and rebuilds state.
The maintained reference path remains the fallback whenever admission, capability, lifetime, or validation is uncertain. A fast result with an unproven dependency is not acceptable as an exact optimization.
- Can dramatically reduce vCPU CPU use in hot waits
- Does not fabricate final guest register/flags
- Narrow title/runtime loop can be thoroughly tested
- Useful even if completion latency is unchanged
- Lost wakeups/deadlocks
- False recognition changes guest work
- Timeout/interrupt timing differences
- Producer may require the waiting vCPU to run
- Title/code-version specificity
Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:
- recognized_loop_entries
- iterations_avoided
- MMIO_reads_avoided
- wait_duration
- spurious_wakes
- reference_fallbacks_by_reason
- producer_latency
- vCPU CPU time
A local reduction is not enough. Evidence must connect route reachability and removed work to fixed guest progress, CPU/GPU time where applicable, and p95/p99 behavior.
- Completion before/during/after registration
- Spurious wake and never-completing producer
- Interrupt/timer arrival
- Loop with counter/side effect/timeout must reject
- Self-modifying code
- MMIO remap
- Snapshot/reset
- Producer dependency/deadlock analysis
Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.
Promote only one proven loop at a time with a complete wake/invalidation model, large avoided-iteration evidence, and unchanged guest completion behavior.
Reject generic heuristics or any recognized loop whose producer, timeout, or side effects are not fully understood.
CPU-and-vCPU-Execution · Performance-Unproven · Hot-Path-PGRAPH-Fast-Fence-Polling · Timing-Clocks-and-Timers
PR pages may be linked as supporting evidence, but they are not substitutes for this reference.
DSP tooling guide and navigation updated November 2, 2026 for experimental PR #384, source 8f51d237. Capture/replay usage and limits.
The earlier wiki-wide review was published November 1, 2026. Emulator source: b7140848. Reviewed wiki content: 1d2b671. Current status · Release availability · Publication process.
- Home
- Current status
- Stable versus main
- Implemented mechanisms
- Controls and defaults
- Measured results and limits
- Complete change register
- System
- CPU and vCPU
- Memory and DMA
- Graphics / NV2A
- APU and audio
- Timing and timers
- Platform and I/O
- Hardware observations
- Fidelity boundaries
- Methodology
- PGR2 routes
- Debugging lag / hot paths
- Tools and commands
- DSP capture, replay and fuzzing
- HLE readiness and public XISO proof
- Concurrent DSP shadow and OpenAL proof
- DSP HLE operation inventory
- DSP HLE fix examples and testing
- Development
- Upstream shortlist
- Wiki maintenance
- Research / retired work
- Optimization catalog
- Hot-path shortcuts
- Researched experiments
- Unproven proposal directory
- PR lessons
- September26 snapshot
Repository · PRs · Issues