You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
uci_wait_idle unbounded spin: phantom-socket failure manifests as 600s hang instead of clean error #37
uci_wait_idle spins indefinitely on the lda UCI_STATUS + fence loop with no retry budget. When upstream code feeds garbage into the UCI command pipe (e.g., the phantom-socket bug — see companion issue #36), the C64 spends hundreds of seconds and hundreds of thousands of register accesses waiting for a state change that never comes, instead of failing cleanly with a wall-clock-bounded timeout.
Discovery context
Surfaced during validation of c64-test-harness issue #90 (JC-000/c64-test-harness#90). Test tools/uci/test_https_local.py reaches the 600 s sentinel timeout because the C64 spends 605 s and 227k UCI register accesses (≈99% of total bus traffic) in this single PC range.
src/net/uci/uci_cmd.s:69-76 — uci_wait_idle. The unbounded design is intentional per the project's design notes, but for callers driven by host-side DMA/monitor (where wall-clock failure is preferable to indefinite hang) an opt-in bounded variant is appropriate.
DebugCapture trace from a wedged run (/tmp/uci_https_debug/20260510_104617/tail.txt) shows >350k hits each at PCs $2307–$230B — every single one is the lda UCI_STATUS + fence sequence. Interspersed are lone $DF1D writes every ~2k cycles when net_tcp_send's retry path issues a CMD_DATA push. The spin re-enters immediately after each write.
Suggested fix
Two viable shapes:
Option A: opt-in bounded variant (preferred)
Keep the existing unbounded uci_wait_idle for paths where indefinite spin is correct (boot, init). Add a sibling uci_wait_idle_bounded(timeout_jiffies) that returns CARRY-set on timeout. Migrate network-IO retry paths (net_tcp_send, net_tcp_recv, tls_*) to the bounded variant. Bound budget can be a build-time constant (e.g., 60 jiffies = ~1 s).
Option B: global hard cap
Add a single global cycle-counter check inside uci_wait_idle that gates the spin on a configurable upper bound (e.g., 5–10 s wall-clock-equivalent). Smaller diff; less surgical. Risk: changes semantics for paths that legitimately want unbounded spin.
Option A is cleaner — preserves existing behavior, adds a new tool, callers opt in.
Severity
Medium alone — symptomless without an upstream fault. But paired with the phantom-socket bug in #36, this bug is what converts a transient firmware fault into a 600 s test hang. Bounded spin would surface the underlying failure within seconds, making CI feedback and bisection dramatically faster.
Verification
After fix: tools/uci/test_https_local.py should fail in <2 s with a clean error pointing at net_tcp_send (or wherever the bounded uci_wait_idle returns CARRY-set), instead of hanging for 600 s.
Activity
chore: baseline catchup — pre-session local work (cc65 debug info + o…