This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
xenia-rs/native-gate.sh
MechaCat02 48e166579b [iterate-4E] Stage 0: native-threads mode flag + functional gate
Scaffolding for the canary-model rework (host-thread-per-guest-thread,
opt-in, non-deterministic). No behavior change with the flag off.

- XENIA_NATIVE_THREADS=1 selects the new executor; folded into the
  parallel spawn gate (reuses Arc<Mutex<KernelState>> + worker dispatch).
- native_threads_enabled() = single source of truth for guarded branches.
- run_execution_native(): Stage-0 body delegates to the iterate-4D
  free-run executor verbatim (native == freerun for now); Stage 1' will
  replace the worker set with one host thread per guest thread.
- native-gate.sh: functional oracle replacing byte-goldens for the MT
  path — (1) lockstep golden byte-identity (flag-off safety net),
  (2) native render milestone (draws>0 && swaps>0), (3) native deadlock
  stress. GREEN 3/3 on current code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:18:28 +02:00

88 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# native-gate.sh — functional correctness gate for the iterate-4E canary-model
# native-threads rework (host-thread-per-guest-thread, non-deterministic).
#
# Byte-identical goldens cannot gate a multi-threaded run (OS interleaving is
# nondeterministic), so this script is the REPLACEMENT oracle. It runs three
# checks and exits 0 iff all pass:
#
# 1. LOCKSTEP GOLDEN (flag-off): the deterministic default path stays
# byte-identical on sylpheed_n200m.json. This is the safety net that
# proves the native-mode work did not disturb the reference path.
# 2. NATIVE RENDER MILESTONE: native mode (XENIA_NATIVE_THREADS=1) boots far
# enough to render — draws>0 && swaps>0 in the run digest — proving the
# executor runs guest CPU + drives the GPU end-to-end without hanging.
# 3. NATIVE DEADLOCK STRESS: parallel_stress_short under XENIA_NATIVE_THREADS=1
# with --halt-on-deadlock; N back-to-back short runs with no panic/hang,
# surfacing lost-wakeups / lock-order inversions the single run misses.
#
# Usage: [SYLPHEED_ISO=...] native-gate.sh [milestone_n] [milestone_timeout_s]
# milestone_n default 200000000 (renders; matches the golden anchor)
# milestone_timeout_s default 120
#
# The binary must be built first (the caller owns the build so the OOM guardrail
# CARGO_BUILD_JOBS=4 / free-check stays explicit):
# CARGO_BUILD_JOBS=4 cargo build --release
set -u
cd "$(dirname "$0")" || exit 2
BIN=./target/release/xenia-rs
ISO_CHECK=sylpheed.iso
MN="${1:-200000000}"
MTO="${2:-120}"
DIGEST=/tmp/native-gate-digest.json
LOG=/tmp/native-gate
mkdir -p "$LOG"
fails=0
hr(){ printf '=%.0s' {1..64}; echo; }
[ -x "$BIN" ] || { echo "FAIL: build first: CARGO_BUILD_JOBS=4 cargo build --release"; exit 3; }
# ---------------------------------------------------------------- 1) golden
hr; echo "[1/3] LOCKSTEP GOLDEN — flag-off byte-identity (sylpheed_n200m)"; hr
cargo test --release -p xenia-app --test sylpheed_oracles -- \
--ignored --nocapture sylpheed_n200m >"$LOG/golden.log" 2>&1
rc=$?
if [ $rc -eq 0 ]; then echo " PASS (golden byte-identical)"; else
echo " FAIL rc=$rc — see $LOG/golden.log"; tail -20 "$LOG/golden.log"; fails=$((fails+1)); fi
# ------------------------------------------------------- 2) native milestone
hr; echo "[2/3] NATIVE RENDER MILESTONE — XENIA_NATIVE_THREADS=1, -n $MN"; hr
rm -f "$DIGEST"
XENIA_NATIVE_THREADS=1 timeout "$MTO" "$BIN" check "$ISO_CHECK" \
-n "$MN" --gpu-inline --out "$DIGEST" >"$LOG/milestone.log" 2>&1
rc=$?
pkill -x xenia-rs 2>/dev/null
if [ $rc -ne 0 ]; then
echo " FAIL emulator rc=$rc (timeout=$MTO s) — see $LOG/milestone.log"
tail -20 "$LOG/milestone.log"; fails=$((fails+1))
elif [ ! -f "$DIGEST" ]; then
echo " FAIL no digest written — see $LOG/milestone.log"; fails=$((fails+1))
else
read -r draws swaps instrs < <(python3 - "$DIGEST" <<'PY'
import json,sys
d=json.load(open(sys.argv[1]))
print(d.get("draws",0), d.get("swaps",0), d.get("instructions",0))
PY
)
echo " digest: instructions=$instrs draws=$draws swaps=$swaps"
if [ "${draws:-0}" -gt 0 ] && [ "${swaps:-0}" -gt 0 ]; then
echo " PASS (native mode renders)"
else
echo " FAIL (native mode did not render: draws=$draws swaps=$swaps)"; fails=$((fails+1)); fi
fi
# ---------------------------------------------------------- 3) native stress
hr; echo "[3/3] NATIVE DEADLOCK STRESS — parallel_stress_short (native)"; hr
XENIA_NATIVE_THREADS=1 cargo test --release -p xenia-app --test parallel_stress -- \
--nocapture parallel_stress_short >"$LOG/stress.log" 2>&1
rc=$?
if [ $rc -eq 0 ]; then
grep -o "runs=[0-9]* ok=[0-9]* failed=[0-9]*" "$LOG/stress.log" | tail -1
echo " PASS (no deadlock/panic)"
else
echo " FAIL rc=$rc — see $LOG/stress.log"; tail -20 "$LOG/stress.log"; fails=$((fails+1)); fi
hr
if [ "$fails" -eq 0 ]; then echo "NATIVE GATE: PASS (3/3)"; exit 0
else echo "NATIVE GATE: FAIL ($fails/3 checks failed)"; exit 1; fi