S-1b follow-up: free the refused word's metrics context_window; correct the pipelining claim; review record
- vm_create_word()'s S-1b refusal path now calls transition_metrics_cleanup() before freeing the metrics struct (its context_window leaked). - FABRIC-3.9.8: the transition_heat grow is untested -- ENABLE_PIPELINING=0 in the kernel AND the default hosted build; the doc wrongly said hosted. - Recorded the review: moving id tables have no unlocked or interrupt readers (heartbeat lookups hold dict_lock, as does the grow); sweep for other word-id-indexed arrays found none unbounded. Status line updated. 3-ISA acceptance passes; boot parity and dict_hash set unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1dbd0c74ed
commit
a2e3356b2e
+22
-4
@@ -1,7 +1,7 @@
|
||||
# FABRIC-3.9.8.md — Observers and participants: execution plan and log
|
||||
|
||||
**Status: PLANNED. No stage started.** The design and its open rulings (O-1 to O-4, plus the
|
||||
discard question) are in `FABRIC-3.9.0.md`.
|
||||
**Status: IN PROGRESS.** Done: O-A, the stack-convention fix, S-1a and S-1b (§2). The design and
|
||||
its rulings (O-1 to O-4, the discard, and §7/§8's M- and S- rulings) are in `FABRIC-3.9.0.md`.
|
||||
|
||||
Each stage:
|
||||
- needs Captain Bob's explicit go;
|
||||
@@ -267,8 +267,9 @@ Evidence is named **before** each stage runs.
|
||||
- Every reader bounds by that field. `get_probability` had no bounds check at all.
|
||||
- A failed grow drops that one transition (the word already ran; nothing is left to refuse).
|
||||
It is logged and counted (`transition_metrics_grow_failures()`).
|
||||
- Pipelining is compiled out of the kernel (`ENABLE_PIPELINING=0`), so this path is live
|
||||
only in hosted builds.
|
||||
- **Untested at runtime.** Pipelining is compiled out of the kernel *and* the default
|
||||
hosted build (`ENABLE_PIPELINING=0` in both), so this grow path is dead in every shipped
|
||||
configuration. No run exercised it. It is corrected, not proven.
|
||||
- **Stadium's id→cell rows (`stadium_words.c`).** These were `[slot][DICTIONARY_SIZE]`.
|
||||
- Each row now starts empty and grows on dispatch (`row_cap[slot]`), not at definition,
|
||||
because a quota slot can be granted after a VM's words exist, and slots are reused across
|
||||
@@ -320,3 +321,20 @@ Evidence is named **before** each stage runs.
|
||||
`vm_dictionary_word_id_refusals()`, `transition_metrics_grow_failures()`,
|
||||
`stadium_words_row_grow_failures()`). Adding a word changes the `dict_hash` set, so this
|
||||
awaits Captain Bob's ruling.
|
||||
|
||||
**Follow-up review (same day, own commit; acceptance `logs/20260924-140359/amd64/`, `-141643/aarch64/`, `-142946/riscv64/`: boot parity and `dict_hash` set unchanged, O-A checks, relay `3`, idle growth 0, no faults):**
|
||||
- **The refusal path leaked each metrics' `context_window`.** It freed the
|
||||
`WordTransitionMetrics` struct without `transition_metrics_cleanup()`. That call is now made
|
||||
first.
|
||||
- **Moving tables were checked for concurrent readers.** Before S-1b the id map never moved;
|
||||
now a grow frees the old map, and likewise the Stadium rows. Every id lookup off the
|
||||
interpreter path runs under `dict_lock`: the heartbeat decay cursor (`vm_time.c`,
|
||||
`vm_runtime.c`), the rolling-window seed, and inference. `vm_create_word()` holds that
|
||||
lock across the grow. In the kernel, the heartbeat is mainline and execution-paced, not an
|
||||
interrupt, and Stadium rows are touched only from the interpreter and
|
||||
`stadium_words_resident_heat`'s FORTH word. No interrupt reads either.
|
||||
- **Sweep for other arrays indexed by word ids** (not only those named `DICTIONARY_SIZE`):
|
||||
- `rolling_window_find_hottest_word()` sizes by its own `dict_size` parameter and has no
|
||||
callers.
|
||||
- No word-id field narrower than 32 bits.
|
||||
- Nothing else found.
|
||||
|
||||
Reference in New Issue
Block a user