Repository navigation
Hot Path PFIFO Constant Status Read
Lifecycle: Performance - Unproven · Type: Assumption lock bypass
State: Source-backed; runtime value is not established.
Status: Source-backed low-priority MMIO experiment; not implemented as a lock-free path and not benchmarked.
Reviewed source:
322986f4c5502b3fa887a9605ac8cd88e9b2c579Scope: Exact reads of
NV_PFIFO_RUNOUT_STATUSinpfifo_read().
This is the literal “xemu already knows the response” candidate from the additional audit. The current handler acquires the PFIFO mutex and enters the general register switch, but the NV_PFIFO_RUNOUT_STATUS branch returns a fixed xemu value without consulting mutable PFIFO state.
It is a candidate for one narrow early-read path—not a proposal to make status registers generally constant or to bypass MMIO semantics.
Current flow is effectively:
MMIO read
-> acquire pfifo.lock
-> switch address
-> RUNOUT_STATUS returns LOW_MARK
-> release lock
-> register logging
The returned value is currently:
NV_PFIFO_RUNOUT_STATUS_LOW_MARK /* low mark empty */The lock protects other PFIFO registers and state, but this branch does not read that state.
This is not already covered by Fast Fence Polling. The fence path serves an asynchronously changing PGRAPH register with ordered atomic publication. This candidate serves a constant value in xemu's current model and has a different proof obligation.
Potentially avoided work is limited to:
- PFIFO mutex acquisition/release;
- contention with the PFIFO pusher/puller thread;
- general switch execution after an exact-address check.
However, MMIO dispatch, TCG exit/dispatch and register logging may dominate. This candidate matters only if guest software reads the status frequently and lock wait or lock traffic is measurable.
flowchart TD
A[Guest MMIO read] --> B[QEMU MemoryRegion dispatch]
B --> C[pfifo_read]
C --> D[Acquire pfifo.lock]
D --> E[Switch register address]
E -->|RUNOUT_STATUS| F[Return LOW_MARK constant]
F --> G[Release pfifo.lock]
G --> H[Log register read]
H --> I[Return to guest]
flowchart TD
A[Guest MMIO read] --> B[QEMU MemoryRegion dispatch]
B --> C[pfifo_read]
C --> D{Exact RUNOUT_STATUS access accepted?}
D -->|Yes| E[Use current modeled LOW_MARK value]
E --> F[Preserve register logging]
F --> G[Return to guest without pfifo.lock]
D -->|No| H[Acquire pfifo.lock]
H --> I[Use existing general register path]
I --> J[Release lock and log]
Before bypassing the lock, verify the same conditions as the current MMIO registration/handler contract:
- exact register address;
- accepted access width and alignment;
- endianness and masking behavior;
- register logging/tracing;
- no required side effect on read;
- reset/snapshot behavior of the modeled value;
- error behavior for unsupported access sizes.
Do not copy the PGRAPH fence path mechanically. A memory barrier pair is meaningful for a changing published fence value; it is unnecessary decoration for a true constant and could hide that the model itself should be improved instead.
The fixed response is an xemu implementation choice, not proof that physical NV2A hardware returns the value unconditionally under every FIFO condition.
The shortcut preserves current xemu behavior. If future hardware research implements dynamic runout state, this early path must be removed or changed to read the authoritative state.
Therefore the page and code should label the route as:
constant in the current model
not:
hardware constant
Internal xemu precedent: narrowly specialized MMIO paths already exist where a register has a proven cheaper access contract, including the PGRAPH fence fast path and direct fixed responses in other NV2A blocks.
General emulator precedent: device models often use direct handlers for side-effect-free constant or capability registers. The optimization is only useful when the register is hot; correctness comes from matching the device model's access contract, not from the constant itself.
| Area | Role |
|---|---|
hw/xbox/nv2a/pfifo.c::pfifo_read() |
Current locked read and constant branch |
| PFIFO mutex | Protects mutable PFIFO state used by other registers |
| MMIO registration/MemoryRegionOps | Defines valid sizes/alignment/endianness |
| NV2A register logger | Must remain observable when enabled |
| vCPU thread | Executes the guest MMIO read |
| PFIFO worker | Potential lock-contention peer |
Before code changes, measure:
pfifo_mmio_reads
pfifo_runout_status_reads
pfifo_read_lock_acquisitions
pfifo_read_lock_wait_ns
pfifo_runout_status_read_cpu_ns
TCG/MMIO dispatch samples around the read
After a candidate:
runout_fast_reads
runout_reference_reads
unsupported_width_fallbacks
value/oracle mismatches
A high register-read count with negligible lock wait may still yield no useful improvement because the MMIO/TCG boundary remains.
- Optimizing a cold register and adding permanent complexity for no gain.
- Bypassing access-width or logging behavior.
- Treating a current stub value as hardware truth.
- Leaving the fast path after a future dynamic runout implementation.
- Moving the bottleneck to MMIO/TCG dispatch with no guest-progress improvement.
- Broadening the idea into unsafe lock-free reads of mutable PFIFO registers.
- Count the register in representative titles before implementing.
- Confirm accepted access sizes and logging with focused MMIO tests.
- Add same-binary reference/fast route counters.
- Stress simultaneous guest reads and PFIFO worker activity.
- Compare exact returned values and traces.
- Profile vCPU/MMIO/lock cost in optimized Release builds with matching DWARF.
- Measure fixed guest progress and tails, not only helper nanoseconds.
- Add a source comment that invalidates the shortcut if runout status becomes dynamic.
- Remove the candidate if the route is cold or the improvement is below maintenance value.
Applicable as a tiny measurement-driven experiment, not a priority feature. Add counters first. A permanent Advanced control is unlikely to be justified if the modeled response remains exact and exhaustive tests pass.
Primary reference: This subject page is the design and research reference for PFIFO Constant Status Read. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Current-model constant-response lock bypass
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579· Acceptance class: intended exact or behavior-preserving for its admitted scope
Return the value already modeled as constant for NV_PFIFO_RUNOUT_STATUS without taking the general PFIFO mutex, if access semantics and instrumentation remain intact.
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/pfifo.c |
pfifo_read() and NV_PFIFO_RUNOUT_STATUS handling |
flowchart TD
N0["Guest MMIO read"]
N1["Enter generic PFIFO read route"]
N0 --> N1
N2["Acquire PFIFO mutex"]
N1 --> N2
N3["Switch on register"]
N2 --> N3
N4["Return LOW_MARK constant"]
N3 --> N4
N5["Release mutex"]
N4 --> N5
flowchart TD
N0["Guest MMIO read"]
N1["Recognize exact address/width"]
N0 --> N1
N2["Return current-model constant atomically"]
N1 --> N2
N3["Use generic route for every other case"]
N2 --> N3
The register branch returns a fixed value without consulting mutable PFIFO state. If the guest polls it frequently and lock acquisition contributes material cost, a narrow early return can preserve current emulator behavior while avoiding contention. This does not prove the physical hardware register is constant.
- PFIFO mutex acquisition/release
- Generic register switch dispatch for this exact read
- MMIO decode
- Access-size/alignment checks
- Tracing and counters
- Every other register
- Future model changes that make status dynamic
if (addr == NV_PFIFO_RUNOUT_STATUS && size == 4 &&
current_model_runout_is_constant) {
stats.runout_fast_reads++;
return NV_PFIFO_RUNOUT_STATUS_LOW_MARK;
}
return pfifo_read_reference(d, addr, size);The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.
- The fast value must equal the reference path for the same access.
- Access width, alignment, endianness, tracing, and fault behavior must remain identical.
- The shortcut must be removed or disabled if the model gains mutable runout state.
No cached mutable object is required. The safety contract is tied to the current register model and should be encoded with a focused helper/assertion rather than a broad 'constant MMIO' framework.
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.
- Very small change
- Exact maintained fallback
- Can reduce lock contention in a true poll loop
- Easy same-binary A/B and differential testing
- Likely negligible if MMIO/TCG dispatch dominates
- Can fossilize an incomplete hardware model
- Broadening to other registers would be dangerous
- Added branch may cost more when the register is rare
Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:
- runout_status_reads
- runout_fast_reads
- generic_pfifo_reads
- pfifo_lock_wait_us
- vCPU samples in MMIO dispatch
- guest progress
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.
- Compare fast/reference return and side effects
- All access widths/alignment cases
- Concurrent PFIFO activity
- Trace/counter parity
- A title or synthetic loop that reads the register heavily
- Release A/B with route counters disabled for acceptance
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 if the register is read frequently enough and lock/dispatch measurements show repeatable benefit while preserving the current model exactly.
Reject if route frequency is low, the lock is uncontended, MMIO dispatch dominates, or the register should become stateful for fidelity.
Platform-and-I-O · Performance-Unproven · Hot-Path-PGRAPH-Fast-Fence-Polling · Hot-Path-vCPU-Recognized-Poll-Loop-Wait
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