Files
xenia-rs/docs/functions/sub_82452DC0.md
MechaCat02 ad45873a1b ITERATE-2.V: scheduler priority aging closes 18-day AUDIT-049 wedge
Priority aging in xenia-cpu/scheduler.rs:pick_runnable
(effective_priority = base + age_bonus(now_round - last_run_round),
capped at +31, AGING_ROUNDS_PER_BONUS=1). Strict-priority was parking
priority=0 threads behind CPU-bound priority=15 audio mixer
(sub_824D1328 guest spinwait at PC=0x824d1404 on CPU5). Aging
eventually picks the starved thread, breaking the producer-consumer
cycle that caused 5-tid wedge at PC=0x824ac578 since AUDIT-049 (10 May).

Cascade observed: tid=13 clean exit; events 121K -> 13M (107x); last
host_ns 767ms -> 51,011ms (66x); 8 new threads spawn; VdSwap 1 -> 2.

Complete two-day iterate sequence (2026-05-27 -> 2026-05-28):
- 2.F: VdSwap drain timeout 900ms -> 1ms (xenia-gpu/handle.rs); 876x
       perf win on VdSwap kernel callback
- 2.H: vA0000000 physical heap bucket added (state.rs, exports.rs);
       ctx_ptrs now in 0xA0000000-0xBFFFFFFF range matching canary
- 2.L: Phase-A diff harness categorized [return_value mismatch],
       [status mismatch], [args_resolved.path mismatch] tags
       (tools/diff-events/diff_events.py); closes reading-error #41
       (silent test-harness state leak invalidating trace diffs)
- 2.M: always-on exit-thread-state.json sibling to Phase-A JSONL
       (event_log.rs + xenia-app/main.rs); closes reading-error #42
       (Phase-A blind to blocked-forever waits)
- 2.Q: signal.match kernel instrumentation in NtSetEvent /
       NtReleaseSemaphore / KeSetEvent / KeReleaseSemaphore
       (exports.rs); emits target_handle + waiter_count + waiter_tids
- 2.T: wake.requested kernel instrumentation in wake_eligible_waiters
       (exports.rs); emits target_tid + transition + new_state
- 2.V: scheduler priority aging (xenia-cpu/scheduler.rs) [keystone]

Plus accumulated WIP from earlier May (contention_manifest,
phase_b_snapshot, xam/xaudio enhancements, analysis db, xex loader,
xenia-app main loop, etc.). Audit-runs/ artifacts remain untracked
per project convention.

Tests: 300 xenia-cpu / 227 xenia-kernel / 5 xenia-app / 19 xenia-path
/ 30+ smaller suites -- all PASS, 0 regressions. Determinism preserved
(2x cold runs bit-identical at 13,003,881 events post-2.V).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 07:27:26 +02:00

63 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
address: 0x82452DC0
classification: normal_callee
confidence: high
last_audit: 063
aliases:
- "work-submitter"
- "audit-050 root"
---
# sub_82452DC0 — work-submitter / cluster-root
## Synopsis
Central work-submission function. All AUDIT-049060 γ-wedge chains and AUDIT-058 vtable-activation chains funnel through this function. Receives a request (likely a file-IO descriptor + completion XEvent) and dispatches it via 9 direct callees + 1 indirect call. In canary it fires ~3.21× more often than in ours per AUDIT-056 — the upstream gate is in its caller, not in it.
## Evidence
- AUDIT-050 enumerated 9 direct targets at `bl` sites: `0x8245AE50, 0x82452068, 0x82452200, 0x8245B000, 0x8245B078, 0x82454A40, 0x82452AB8, 0x82454918, 0x82452EC4`, plus 1 `ind_call`.
- AUDIT-051 found a predicate gate at `+0x78`: `0x82452E2C beq cr6, 0x82452E88`, controlled by `sub_8245B000(r3)` returning 1 iff `[r3+0]≠0 AND [r3+4]≠0`. The 80-byte stack-local struct lives at `r31+96`.
- AUDIT-052 found `[r3+0]` / `[r3+4]` are halves of a hash key formatted into `cache:\<HASH1>\<X>\<HASH2>` paths — i.e. the struct holds a content hash for cache resolution. Predicate refuted as the bug.
- AUDIT-055 probed `sub_8245B078`'s body with a cache override: body executes correctly; divergence is upstream.
- AUDIT-056: fires **canary 45/60s, ours 14/26s = 3.21× ratio**. Sharpest specific divergence: `sub_8217FA08` from `LR=0x82455E60` (`=sub_82455DF0+0x70`) canary 20 / ours 0.
- AUDIT-059: tid=13 itself fires `sub_82452DC0` once at LR=`0x821cb1d0` (from `sub_821CB030+0x19C`) immediately before waiting on the file-IO completion XEvent.
- AUDIT-060: confirmed convergence — `sub_8245FEB8 ← sub_824601A0 ← sub_82460118 ← sub_82452AB8 ← sub_82452DC0`. The vptr-installer chain bottoms out here.
## Activation
Direct `bl` from 34 static caller sites per AUDIT-051. Notable callers:
- `sub_821CB030+0x19C` — drives the file-IO completion submission used by `silph::GamePart_Title::UImpl`.
- `sub_821CB030+0x2BC` — second site in same fn.
- `sub_821C4EB0` chain (AUDIT-056 gate).
- `sub_82173990+0x208` (program-top frame).
## Static graph
- Static callers: 34 sites across boot + tid=13 + UI cluster.
- Static callees (direct `bl`): 9 functions above + 1 computed call.
- The 9-target tree is the "worker activation surface". `sub_82452AB8` is the gate leading to vptr installers; `sub_8245B078`, `sub_8245B000` are the cache-key/hash gates; the others are queue management.
## Audit log
- **AUDIT-063 (2026-05-12)** — static reachability surveyed: among the 60 distinct callers of NtSet wrapper `0x824AA2F0`, **only 1 is reachable within 12 hops from `sub_82452DC0`**: `sub_8245FEB8` (γ-signaler C). The AUDIT-062 candidate trio (`sub_822F2248`, `sub_822F1AA8`, `sub_821741C8`) are NOT downstream. Confirms that the "producer-side worker-wake signal" canary path is the worker cluster (`sub_82458B90`/`sub_8245EC10`/`sub_8245FEB8`/`sub_8245D9D8`/`sub_8245DA78`) reached via the 4 worker threads spawned by `sub_825070F0` — and those threads are unspawned in ours (0 vs 8 in canary). [confirmed]
- **AUDIT-060 (2026-05-12)** — confirmed as single funnel for AUDIT-058+059 chains; the work-submitter is alive and queues but the throughput is gated by `sub_821C4EB0` early-exit per AUDIT-056. [confirmed]
- **AUDIT-059 (2026-05-11)** — fires 8× in ours; one of those is tid=13 from `sub_821CB030+0x19C` right before waiting on the wedge XEvent. Work submitted but no signal returns. [confirmed]
- **AUDIT-056 (2026-05-10)** — fires canary 45 / ours 14 in matched windows = 3.21× gap. Bug class refined to "δ-throughput". [confirmed]
- **AUDIT-055 (2026-05-10)** — proved `sub_8245B078` body executes correctly; ruled out a downstream bug here. [confirmed]
- **AUDIT-052 (2026-05-10)** — refuted AUDIT-051's "missing population" hypothesis. The struct is bit-identical to canary; `[r3+0]/[r3+4]` are a content hash. [supersedes-AUDIT-051-claim]
- **AUDIT-051 (2026-05-10)** — initially identified `+0x78` predicate gate as bug. [STATUS: hypothesis falsified by AUDIT-052; the gate itself is real and named correctly, but it's not the bug]
- **AUDIT-050 (2026-05-10)** — enumerated 9 direct targets + 1 indirect; framed as activation-surface root. [confirmed]
## Open questions
- Why does `sub_82452DC0` fire 3.21× less in ours? AUDIT-061 pivots to its caller `sub_821C4EB0`'s internal branches `[+0x44, +0xE0]`.
- The 1 indirect call (computed) — what does it dispatch to, and does our static-analyzer miss any of its candidates?
## Cross-references
- Callers: [sub_821CB030](sub_821CB030.md), [sub_821C4EB0](sub_821C4EB0.md)
- Callees-of-interest: [sub_82452AB8](#) (not yet dossierd), `sub_8245B078`, `sub_8245B000` (cache-hash gate)
- Audits: 049, 050, 051, 052, 053, 054, 055, 056, 057, 058, 059, 060
- Artifacts: `audit-runs/audit-050-*/`, `audit-runs/audit-056-producer-trace/`, `audit-runs/audit-059-gamma-wedge/`, `audit-runs/audit-060-fnptr-array-bootstrap/`