D134: task-done SP/DP events must not be dropped into a full sched interruptQ

The frame-2 boot hang blamed on D117 flakiness since M-13 is a real bug:
osSpTaskStartGo posted OS_EVENT_SP/DP with OS_MESG_NOBLOCK into the 8-slot
scheduler interruptQ that the 60 Hz VI pacemaker also fills. A gfx task runs
the whole frame synchronously on the sched thread, so a slow early frame lets
retraces fill the queue and the done event is silently discarded -> curRSPTask
never clears -> pendingGfx never clears -> permanent stall.

portPostEventForce() drops the oldest (stale retrace) message and retries;
portPostVIEvent reserves 2 slots. -level_09: 6/6 boots to frame 600, 0
heartbeats (pre-fix 1/3).

Also hardens tools_pc/level_sweep.sh: 45s watchdog, lockdir serialization,
stray-process kill, one retry on NO-FRAMES.
This commit is contained in:
James Dansereau committed 2026-08-29 23:32:17 -04:00
1 parent 577f32f01f
commit 46d4f03e5a
5 files changed
+142 -19

No files matched your search

+79 -16
View File
@@ -1,33 +1,96 @@
#!/bin/bash
# Level sweep: bare -level_XX boot for all 21 solo levels; PASS/NO-FRAMES/CRASH.
#
# Flakiness notes (M-13..M-21): the port is not frame-deterministic (D117) and
# a loaded machine (a concurrent ninja build, another sweep, a stray ge007)
# routinely turns a known-good level into a spurious NO-FRAMES. This runner is
# therefore SERIALIZED (a lockdir + a stray-process kill before each level) and
# uses a 45 s watchdog, and it RETRIES a NO-FRAMES row once before reporting it.
# Do not run it next to a build.
#
# Env overrides:
# SWEEP_SECS=45 per-level watchdog seconds
# SWEEP_DUMP=80-400:40 GE_PCDUMP window
# SWEEP_LEVELS="Dam:33" subset to run
cd "$(dirname "$0")/.."
LV="Dam:33 Facility:34 Runway:35 Surface1:36 Bunker1:09 Silo:20 Frigate:26 Surface2:43 Bunker2:27 Statue:22 Archives:24 Streets:29 Depot:30 Train:25 Jungle:37 Control:23 Caverns:39 Cradle:41 Aztec:28 Egypt:32 Cuba:54"
SWEEP_SECS=${SWEEP_SECS:-45}
SWEEP_DUMP=${SWEEP_DUMP:-80-400:40}
LV=${SWEEP_LEVELS:-"Dam:33 Facility:34 Runway:35 Surface1:36 Bunker1:09 Silo:20 Frigate:26 Surface2:43 Bunker2:27 Statue:22 Archives:24 Streets:29 Depot:30 Train:25 Jungle:37 Control:23 Caverns:39 Cradle:41 Aztec:28 Egypt:32 Cuba:54"}
OUT=/tmp/sweep_results
mkdir -p /tmp/sweeplogs
LOGS=/tmp/sweeplogs
LOCK=/tmp/ge007_sweep.lock
# --- serialize: one sweep at a time -----------------------------------------
if ! mkdir "$LOCK" 2>/dev/null; then
echo "another sweep holds $LOCK (stale? rmdir it)" >&2
exit 1
fi
trap 'taskkill //F //IM ge007.x86_64.exe >/dev/null 2>&1; rmdir "$LOCK" 2>/dev/null' EXIT INT TERM
export PATH="/c/msys64/mingw64/bin:$PATH" # addr2line + runtime DLLs
mkdir -p $LOGS
: > $OUT
rm -f /tmp/sweeplogs/*.crash.log
for entry in $LV; do
name=${entry%%:*}; num=${entry##*:}
rm -f $LOGS/*.crash.log
# one run of one level -> echoes the status string
run_level() {
local name=$1 num=$2
rm -f ge007.crash.log; rm -rf ppm
export PATH="/c/msys64/mingw64/bin:$PATH"; GE_PCDUMP="80-260:40" ./build-pc/ge007.x86_64.exe -level_$num > /tmp/sweeplogs/$name.log 2>&1 &
pid=$!
sleep 24
# kill anything left over from a previous level / another session
taskkill //F //IM ge007.x86_64.exe > /dev/null 2>&1
sleep 1
GE_PCDUMP="$SWEEP_DUMP" ./build-pc/ge007.x86_64.exe -level_$num > $LOGS/$name.log 2>&1 &
local pid=$!
# watchdog: poll so a clean early exit does not cost the full window
local waited=0
while [ $waited -lt $SWEEP_SECS ] && kill -0 $pid 2>/dev/null; do
sleep 1; waited=$((waited + 1))
done
taskkill //F //IM ge007.x86_64.exe > /dev/null 2>&1
wait $pid 2>/dev/null
sleep 2
status="UNKNOWN"
if [ -f ge007.crash.log ]; then
local pc sym
pc=$(grep -oE '0x[0-9a-fA-F]+' ge007.crash.log | head -1)
sym=$(addr2line -e build-pc/ge007.x86_64.exe -f -C "$pc" 2>/dev/null | head -1)
status="CRASH @ $sym ($pc)"
cp ge007.crash.log /tmp/sweeplogs/$name.crash.log
cp ge007.crash.log $LOGS/$name.crash.log
echo "CRASH @ $sym ($pc)"
return
fi
local last pcnt
last=$(ls ppm/*.ppm 2>/dev/null | tail -1)
if [ -n "$last" ]; then
pcnt=$(python tools_pc/pixcount.py "$last" 2>/dev/null | grep -oE 'non-clear [0-9]+ \([0-9.]+%\)')
echo "PASS $pcnt"
else
last=$(ls ppm/*.ppm 2>/dev/null | tail -1)
if [ -n "$last" ]; then
pcnt=$(python tools_pc/pixcount.py "$last" 2>/dev/null | grep -oE 'non-clear [0-9]+ \([0-9.]+%\)')
status="PASS $pcnt"
echo "NO-FRAMES"
fi
}
for entry in $LV; do
name=${entry%%:*}; num=${entry##*:}
status=$(run_level "$name" "$num")
# NO-FRAMES is the flaky outcome (D117 + host load) -- retry once before
# believing it. A CRASH is deterministic enough to report as-is.
if [ "$status" = "NO-FRAMES" ]; then
sleep 3
retry=$(run_level "$name" "$num")
if [ "$retry" = "NO-FRAMES" ]; then
status="NO-FRAMES (2 attempts)"
else
status="NO-FRAMES"
status="$retry [passed on retry]"
[ -f $LOGS/$name.crash.log ] || true
fi
fi
echo "$name ($num): $status" | tee -a $OUT
done
echo "SWEEP DONE"