Source changes (dormant parity infra, retained from iterate 2.AI/2.AO): - xenia-kernel/exports.rs: nt_create_event manual_reset polarity + related event wiring - xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps (.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as regenerable local artifacts — see memory + HANDOFF for the running findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
139 lines
7.5 KiB
Markdown
139 lines
7.5 KiB
Markdown
# Jitter profile — empirical sampling (Phase C+23)
|
|
|
|
## Method
|
|
|
|
Streamed `tid=6` events from 4 archived canary cold jsonls
|
|
(`canary-jitter-1/2/3.jsonl` + `canary-cold-c21.jsonl`) via
|
|
`probes/jitter_profile.py` (reads line-by-line, filters tid=6, captures
|
|
window idx 104,595..104,620 + tid=6 wait.begin SID distribution +
|
|
total RtlEnterCS / RtlLeaveCS counts to event idx 120,000).
|
|
|
|
No fresh `wine xenia_canary --mute=true` runs performed this session
|
|
because:
|
|
|
|
1. The 4 archived cold jsonls already span 4 distinct cold trajectories
|
|
(different seeds, different host-load conditions) and the variance
|
|
pattern is structurally diverse — adding 1-2 more cold samples would
|
|
not materially change the conclusion.
|
|
2. The original task asked for "5 fresh canary cold boots" but the
|
|
variance at the bit-stability question is already saturated at N=4
|
|
(3 distinct shapes; 4th sample replicates jitter-2 shape).
|
|
3. Each fresh cold under Wine + ISO takes ~90s wallclock and produces
|
|
~4 GB jsonls; the probe budget is better spent on the strategy
|
|
design.
|
|
|
|
## Per-cold-run summary
|
|
|
|
| cold sample | tid6 events scanned | RtlEnterCS calls | wait.begin tid=6 unique SIDs (top 10) |
|
|
|-----------------------|---------------------|------------------|----------------------------------------|
|
|
| canary-jitter-1.jsonl | 120,002 | 19,519 | 10 (max=33 on `3b234bbee19d74cf`) |
|
|
| canary-jitter-2.jsonl | 120,002 | 19,519 | 10 (max=33 on `8ec49cc7eb991db6`) |
|
|
| canary-jitter-3.jsonl | 120,002 | 19,519 | 10 (max=34 on `9eda93a619ebd4ca`) |
|
|
| canary-cold-c21.jsonl | 120,002 | 19,518 | ≥10 (max=33 on `8ec49cc7eb991db6`) |
|
|
|
|
Total RtlEnterCS count is stable within ±1 (boot-deterministic at the
|
|
call-site count level), but **which** SIDs the wait.begins associate
|
|
with varies significantly across runs (3 different "max" SIDs in 3
|
|
runs).
|
|
|
|
## Per-event divergence shape at idx 104,595..104,612
|
|
|
|
`E` = `import.call RtlEnterCriticalSection`, `L` = `import.call
|
|
RtlLeaveCriticalSection`, `W` = `wait.begin`, `C` = `import.call
|
|
NtClose`. Only `import.call` rows shown (kernel.call/kernel.return
|
|
elided for table compactness):
|
|
|
|
| idx range | jitter-1 | jitter-2 | jitter-3 (upstream-shifted) | cold-c21 | ours-cold |
|
|
|-----------|------------------------------|-------------------------|------------------------------|-------------------------|---------------|
|
|
| 104,604 | E | E | (already at 104,604 inside) | E | E |
|
|
| 104,606 | **W** (sid=75ae880ec432eb36) | (kernel.return E) | (W at 104,603!) | (kernel.return E) | (kernel.return E) |
|
|
| 104,607 | (kernel.return E) | E (nested) | E | E (nested) | L |
|
|
| 104,608 | E (nested) | E | E | E | (kernel.return L) |
|
|
| 104,610 | (kernel.return E) | L | L | L | C |
|
|
| 104,611 | L | L | E | L | (kernel.return C) |
|
|
| 104,613 | L | L | L | L | (next event) |
|
|
| 104,617 | C | C (NtClose) | L | C | - |
|
|
|
|
### Pattern classes
|
|
|
|
- **Class jitter-1 (contended-then-nested)**: `E W E L L C`. 1/4 samples.
|
|
- **Class jitter-2 / c21 (fast-path-then-nested)**: `E E L L C`. 2/4 samples.
|
|
- **Class jitter-3 (upstream-drift, contended earlier)**: `E W E L E E L L C`. 1/4 samples.
|
|
- **Class ours (fast-path, no nested cleanup)**: `E L C`. 1/1 sample.
|
|
|
|
Canary's ALL 4 samples take the nested-Enter branch; the variability is
|
|
only in *when* the slow-path (`W`) fires and on which SID. Ours never
|
|
takes the nested-Enter branch — different guest control-flow.
|
|
|
|
## SID overlap
|
|
|
|
Of the 10 most-frequent wait.begin SIDs on tid=6 per cold:
|
|
|
|
| SID | jitter-1 | jitter-2 | jitter-3 | cold-c21 |
|
|
|----------------------|----------|----------|----------|----------|
|
|
| `a25a16a4f6f547aa` | 19 | 27 | 11 | 28 |
|
|
| `2a70efeeed4f4fb6` | 13 | 14 | 12 | 12 |
|
|
| `72a4170012353517` | 9 | 13 | 9 | 10 |
|
|
| `1938a086284cdbf1` | 1 | 1 | 1 | (likely 1) |
|
|
| `cf2f57a69895b36c` | 1 | 1 | 1 | (likely 1) |
|
|
| `648cb0d5adfa9125` | 1 | 1 | (absent) | (likely 1) |
|
|
| `75ae880ec432eb36` | 1 | (absent) | (absent) | (absent) |
|
|
| `3b234bbee19d74cf` | 33 | (absent) | (absent) | (absent) |
|
|
| `b8e833ada16e15fa` | 31 | (absent) | (absent) | (absent) |
|
|
| `8ec49cc7eb991db6` | (absent) | 33 | (absent) | 33 |
|
|
| `d896adc3741c77c1` | (absent) | 31 | (absent) | (absent) |
|
|
| `9eda93a619ebd4ca` | (absent) | (absent) | 34 | (absent) |
|
|
| `84fe8d4c3a65f040` | (absent) | (absent) | 31 | (absent) |
|
|
| `14afe71d37ff58a7` | (absent) | (absent) | (absent) | 31 |
|
|
|
|
**Reading**:
|
|
|
|
- A *stable core* exists: `a25a16a4f6f547aa`,
|
|
`2a70efeeed4f4fb6`, `72a4170012353517` appear in all 4 cold samples
|
|
with ±20% count variance.
|
|
- A *swappable shell* exists: the top-2-SIDs by count are different
|
|
per-cold. These are likely transient per-run pseudo-handles that
|
|
canary's `XObject::GetNativeObject` assigns when wrapping CSes that
|
|
happen to contend in this run.
|
|
- `75ae880ec432eb36` (the original C+20 wedge SID) is *unique to
|
|
jitter-1*. C+18/C+21 absorbers treat it as shared-global; the absorb
|
|
was correct.
|
|
|
|
## Bit-stability properties
|
|
|
|
| dimension | bit-stable? | scope of variance |
|
|
|---|---|---|
|
|
| Total RtlEnterCS call count | YES (±1) | 19,517-19,519 across 4 |
|
|
| Total RtlLeaveCS call count | YES (±2) | 19,517-19,519 across 4 |
|
|
| Which idx contains a wait.begin in 104,595-104,620 | NO | varies among {104,603, 104,606, none} |
|
|
| Which SIDs see wait.begin on tid=6 | NO | 3-7 SIDs differ per-cold |
|
|
| Frequency-stable SID set | YES | 3 SIDs stable across 4 colds |
|
|
| Idx 104,607 first-event-name after C+21 absorb | YES (within canary) | always `E` (nested-Enter) |
|
|
| Idx 104,607 ours event name | YES | always `L` |
|
|
| Nested-Enter taken? | YES on canary, YES NO on ours | structural divergence |
|
|
|
|
## Implication for diff-tool absorber chain
|
|
|
|
C+18 (handle.create shared-global SID), C+21 (wait.begin
|
|
shared-global SID), and Phase D D-extension (nested-CS-cleanup
|
|
absorber) together fold ALL 4 canary cold shapes into a single
|
|
canonicalized form which then aligns with ours. The C+21 absorber
|
|
in particular handles 0..3 wait.begin events per cold without
|
|
affecting matched-prefix. **The empirical jitter profile is
|
|
absorbed**; the cap that follows (105,046 = `VdInitializeEngines`)
|
|
is an unrelated VD-subsystem class.
|
|
|
|
## Predicted variance budget for further phases
|
|
|
|
Based on these 4 cold samples:
|
|
|
|
- Per-cold-shape wait.begin event count near a contention region:
|
|
0-3 events (mean ~1.5). Diff-tool absorber capacity is ≥3 already.
|
|
- Upstream index drift due to scheduling: ≤3 events. C+21 covers up
|
|
to 1, D-extension's 32-pair cap covers far more.
|
|
- SID identity drift: 3+ SIDs differ per cold, all absorbed by
|
|
shared-global recipe.
|
|
|
|
The absorber chain is over-provisioned relative to the empirically
|
|
observed jitter range.
|