handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
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>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Find the canary tid that runs the sub_821748F0 worker body and see
|
||||
what it does in its 155ms lifetime (host_ns 1.935s to ~2.09s).
|
||||
|
||||
The spawn semantic-id is 3bd922fbb385c2c9.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
from collections import Counter
|
||||
|
||||
INPUT = "/home/fabi/RE - Project Sylpheed/xenia-canary/build-cross/bin/Windows/Debug/canary-jitter-1.jsonl"
|
||||
OUTDIR = os.path.dirname(os.path.abspath(__file__))
|
||||
TARGET_HSID = "3bd922fbb385c2c9"
|
||||
|
||||
# First pass: locate this thread's tid by matching the spawn handle.
|
||||
target_tid = None
|
||||
with open(INPUT, "r") as f:
|
||||
for line in f:
|
||||
if '"thread.create"' in line and TARGET_HSID in line:
|
||||
ev = json.loads(line)
|
||||
if ev.get("payload", {}).get("handle_semantic_id") == TARGET_HSID:
|
||||
child_handle = TARGET_HSID
|
||||
print(f" spawn at host_ns={ev['host_ns']}, entry={ev['payload'].get('entry_pc')}")
|
||||
# The thread's own tid will be in events the thread itself emits.
|
||||
# Look for the FIRST event whose tid is NOT the parent and whose
|
||||
# subsequent guest_pc/handle matches this child handle.
|
||||
break
|
||||
|
||||
# We need to find tid by looking at next thread.create's tid_event_idx=0 emission.
|
||||
# Simpler: scan events after this point for new tid that emits with this handle.
|
||||
# Canary's convention: each new thread emits its first events under its own tid.
|
||||
|
||||
# Better approach: find thread.create events with handle_semantic_id=TARGET_HSID,
|
||||
# then find the smallest tid > 6 that emits AFTER that timestamp.
|
||||
|
||||
T_LO = 1_900_000_000 # 1.9s
|
||||
T_HI = 3_000_000_000 # 3.0s
|
||||
|
||||
events_by_tid = {}
|
||||
with open(INPUT, "r") as f:
|
||||
for line in f:
|
||||
if '"host_ns":' not in line:
|
||||
continue
|
||||
try:
|
||||
i = line.index('"host_ns":') + len('"host_ns":')
|
||||
j = i
|
||||
while j < len(line) and (line[j].isdigit() or line[j] == '-'):
|
||||
j += 1
|
||||
host_ns = int(line[i:j])
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
if host_ns < T_LO:
|
||||
continue
|
||||
if host_ns >= T_HI:
|
||||
break
|
||||
try:
|
||||
ev = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
tid = ev.get("tid")
|
||||
if tid is None:
|
||||
continue
|
||||
events_by_tid.setdefault(tid, []).append(ev)
|
||||
|
||||
# tid=6 is parent. Look for new tids that emit between 1.935s and 2.1s.
|
||||
print("\n=== tids active in window [1.9..3.0s] ===")
|
||||
for tid, evts in sorted(events_by_tid.items()):
|
||||
if not evts:
|
||||
continue
|
||||
first_ns = evts[0]["host_ns"]
|
||||
last_ns = evts[-1]["host_ns"]
|
||||
print(f" tid={tid}: {len(evts)} events from {first_ns/1e9:.4f}s to {last_ns/1e9:.4f}s")
|
||||
|
||||
# Find tid that spawns at ~1.935s and ends at ~2.09s.
|
||||
candidate_tid = None
|
||||
for tid, evts in events_by_tid.items():
|
||||
if tid == 6:
|
||||
continue
|
||||
first_ns = evts[0]["host_ns"]
|
||||
if first_ns < 1_930_000_000 or first_ns > 1_960_000_000:
|
||||
continue
|
||||
# Check exit time.
|
||||
last_ns = evts[-1]["host_ns"]
|
||||
print(f" CANDIDATE tid={tid}: first={first_ns/1e9:.4f}s last={last_ns/1e9:.4f}s events={len(evts)}")
|
||||
candidate_tid = tid
|
||||
|
||||
if candidate_tid is None:
|
||||
print("\nNo single candidate found.")
|
||||
else:
|
||||
print(f"\n=== Worker tid={candidate_tid} timeline (sub_821748F0 body) ===")
|
||||
evts = events_by_tid[candidate_tid]
|
||||
# All kernel.calls and thread.create.
|
||||
summary = Counter()
|
||||
for ev in evts:
|
||||
if ev["kind"] == "kernel.call":
|
||||
summary[ev["payload"].get("name", "?")] += 1
|
||||
print(f"Total events: {len(evts)}")
|
||||
print(f"Top kernel.call names:")
|
||||
for n, c in summary.most_common(40):
|
||||
print(f" {c:5d} {n}")
|
||||
# Save full timeline.
|
||||
with open(os.path.join(OUTDIR, f"canary-worker-tid{candidate_tid}-timeline.csv"), "w") as f:
|
||||
f.write("host_ns,tid_event_idx,kind,name,detail\n")
|
||||
for ev in evts:
|
||||
name = ev["payload"].get("name", "")
|
||||
detail = json.dumps(ev["payload"])[:400].replace('"', '""')
|
||||
f.write(f'{ev["host_ns"]},{ev["tid_event_idx"]},{ev["kind"]},{name},"{detail}"\n')
|
||||
print(f"Wrote canary-worker-tid{candidate_tid}-timeline.csv")
|
||||
Reference in New Issue
Block a user