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

4.9 KiB
Raw Blame History

address, classification, confidence, last_audit, aliases
address classification confidence last_audit aliases
0x82452DC0 normal_callee high 063
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_821C4EB0
  • 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/