re: second freeze at ~96s with the inducer on; T74/T75 signature withdrawn
Run 2 put the inducer on from flight start and froze ~96s in, against 670s clean with it off -- n=2, contrast sharp, confounder (elapsed mission time) still untouched. Withdraws last iteration's 'T74/T75 move off a semaphore onto an event' as the signature to chase: it does not reproduce. In run 2 they are on XEvent while HEALTHY and stay there. The healthy state varies between instants, so a one-sample-per-state diff cannot separate a freeze transition from ordinary variation -- I read a difference of samples as a difference of states. Reproduces across both: T68 and T69 go from not-waiting to waiting, T69 on a semaphore and T68 on an event both times. And 21 of 24 threads unchanged in run 2 (17 of 24 in run 1), so 'not a whole-emulator stall' now has two independent captures behind it. Next: repeat the capture several times within one healthy run to establish which thread states are stable before reading any frozen diff.
This commit is contained in:
85
docs/re/data/waitobj-s02-inducer.txt
Normal file
85
docs/re/data/waitobj-s02-inducer.txt
Normal file
@@ -0,0 +1,85 @@
|
||||
=== healthy: 22 wait frames ===
|
||||
T106 Wait n=1 xe::kernel::XEvent
|
||||
T105 Wait n=1 xe::kernel::XEvent
|
||||
T104 Wait n=1 xe::kernel::XEvent
|
||||
T97 Wait n=1 xe::kernel::XEvent
|
||||
T96 Wait n=1 xe::kernel::XEvent
|
||||
T80 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T79 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T78 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T77 Wait n=1 xe::kernel::XEvent
|
||||
T76 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XTimer
|
||||
T75 Wait n=1 xe::kernel::XEvent
|
||||
T74 Wait n=1 xe::kernel::XEvent
|
||||
T71 Wait n=1 xe::kernel::XEvent
|
||||
T67 Wait n=1 xe::kernel::XEvent
|
||||
T66 Wait n=1 xe::kernel::XEvent
|
||||
T65 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T64 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T63 Wait n=1 xe::kernel::XSemaphore
|
||||
T62 Wait n=1 xe::kernel::XEvent
|
||||
T61 Wait n=1 xe::kernel::XEvent
|
||||
T50 Wait n=1 xe::kernel::XEvent
|
||||
T36 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XEvent
|
||||
--- objects waited on:
|
||||
xe::kernel::XEvent 22
|
||||
xe::kernel::XSemaphore 6
|
||||
xe::kernel::XTimer 1
|
||||
=== frozen: 23 wait frames ===
|
||||
T106 Wait n=1 xe::kernel::XEvent
|
||||
T105 Wait n=1 xe::kernel::XEvent
|
||||
T104 Wait n=1 xe::kernel::XEvent
|
||||
T97 Wait n=1 xe::kernel::XEvent
|
||||
T96 Wait n=1 xe::kernel::XEvent
|
||||
T80 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T79 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T78 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T77 Wait n=1 xe::kernel::XEvent
|
||||
T76 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XTimer
|
||||
T75 Wait n=1 xe::kernel::XEvent
|
||||
T74 Wait n=1 xe::kernel::XEvent
|
||||
T71 Wait n=1 xe::kernel::XEvent
|
||||
T69 Wait n=1 xe::kernel::XSemaphore
|
||||
T68 Wait n=1 xe::kernel::XEvent
|
||||
T67 Wait n=1 xe::kernel::XEvent
|
||||
T66 Wait n=1 xe::kernel::XEvent
|
||||
T65 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T64 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore
|
||||
T63 Wait n=1 xe::kernel::XSemaphore
|
||||
T62 Wait n=1 xe::kernel::XEvent
|
||||
T61 Wait n=1 xe::kernel::XEvent
|
||||
T50 Wait n=1 xe::kernel::XEvent
|
||||
--- objects waited on:
|
||||
xe::kernel::XEvent 21
|
||||
xe::kernel::XSemaphore 7
|
||||
xe::kernel::XTimer 1
|
||||
=== healthy -> frozen ===
|
||||
xe::kernel::XEvent 22 -> 21 CHANGED
|
||||
xe::kernel::XSemaphore 6 -> 7 CHANGED
|
||||
xe::kernel::XTimer 1 -> 1
|
||||
=== per-thread healthy -> frozen ===
|
||||
thread healthy frozen
|
||||
T106 Wait(XEvent) Wait(XEvent)
|
||||
T105 Wait(XEvent) Wait(XEvent)
|
||||
T104 Wait(XEvent) Wait(XEvent)
|
||||
T97 Wait(XEvent) Wait(XEvent)
|
||||
T96 Wait(XEvent) Wait(XEvent)
|
||||
T80 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore)
|
||||
T79 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore)
|
||||
T78 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore)
|
||||
T77 Wait(XEvent) Wait(XEvent)
|
||||
T76 WaitMultiple(XEvent,XTimer) WaitMultiple(XEvent,XTimer)
|
||||
T75 Wait(XEvent) Wait(XEvent)
|
||||
T74 Wait(XEvent) Wait(XEvent)
|
||||
T71 Wait(XEvent) Wait(XEvent)
|
||||
T69 -- Wait(XSemaphore) <-- CHANGED
|
||||
T68 -- Wait(XEvent) <-- CHANGED
|
||||
T67 Wait(XEvent) Wait(XEvent)
|
||||
T66 Wait(XEvent) Wait(XEvent)
|
||||
T65 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore)
|
||||
T64 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore)
|
||||
T63 Wait(XSemaphore) Wait(XSemaphore)
|
||||
T62 Wait(XEvent) Wait(XEvent)
|
||||
T61 Wait(XEvent) Wait(XEvent)
|
||||
T50 Wait(XEvent) Wait(XEvent)
|
||||
T36 WaitMultiple(XEvent,XEvent) -- <-- CHANGED
|
||||
@@ -1042,3 +1042,51 @@ unpacking and comparing every word in Python takes **~4.2 s per pass**.
|
||||
**The experiment that would settle it:** alternate inducer-on and inducer-off
|
||||
windows within one run, several runs, and compare freeze rate per unit of
|
||||
*mission* time. Cheap now that `watch` is event-driven.
|
||||
|
||||
## ✅ 2026-08-25 — second freeze, and it REFUTES the signature I named
|
||||
|
||||
Ran the control's opposite: inducer **on from the moment flight begins**
|
||||
(`freeze_waitobj.sh run` with `SYLPH_INDUCE=1`, launched detached so no `timeout`
|
||||
can kill the process group).
|
||||
|
||||
| run | inducer | outcome |
|
||||
|---|---|---|
|
||||
| 1 | off for 670 s, then on | clean 670 s, then **frozen 54 s** after it started |
|
||||
| 2 | **on from flight start** (10:07:20) | **frozen ~96 s later** (10:08:56) |
|
||||
|
||||
Both freezes land inside the 27–255 s band the old heavy-probe runs froze in,
|
||||
and the one long clean stretch is the only window with no inducer. **n=2, and the
|
||||
contrast is now sharp** — but it is still two runs, the confounder (elapsed
|
||||
mission time) is untouched, and the alternating-window test is what would settle
|
||||
it.
|
||||
|
||||
### 🔴 WITHDRAWN: "T74/T75 move off a semaphore onto an event"
|
||||
|
||||
Last iteration I called that "the pair to chase — the only threads that change
|
||||
what *kind* of object they wait for". **It does not reproduce.** In run 2, T74
|
||||
and T75 sit on `Wait(XEvent)` in the *healthy* capture and stay there when
|
||||
frozen.
|
||||
|
||||
The reason is a sampling error I should have caught: the **healthy** state is not
|
||||
fixed either. Run 1 happened to catch T74/T75 on a semaphore; run 2 caught them
|
||||
on an event. A one-sample-per-state comparison cannot tell a freeze transition
|
||||
from ordinary variation between two instants, and I read a difference of samples
|
||||
as a difference of states.
|
||||
|
||||
### ✅ What DOES reproduce across both freezes
|
||||
|
||||
**T68 and T69 go from not-waiting to waiting, in both runs** — and T69 lands on
|
||||
an `XSemaphore` both times, T68 on an `XEvent` both times. Everything else is
|
||||
run-specific: run 1 also parked T105/T67, run 2 instead dropped T36 out of its
|
||||
wait.
|
||||
|
||||
And in both runs the great majority of threads are untouched — 17 of 24 in run 1,
|
||||
**21 of 24** in run 2 — which keeps the one structural claim that has now
|
||||
survived two independent captures: **the freeze is not a whole-emulator stall.**
|
||||
|
||||
Data: `data/waitobj-s02.txt` (run 1), `data/waitobj-s02-inducer.txt` (run 2).
|
||||
|
||||
**Still open:** whether T68/T69 are cause or consequence; one sample per state
|
||||
cannot say. The fix for the error above applies here too — **repeat the capture
|
||||
several times within a single healthy run** to learn which thread states are
|
||||
stable before reading any frozen diff as meaningful.
|
||||
|
||||
Reference in New Issue
Block a user