sk_repl_idle() auto-flush: implement Section V's "anything dirty? no? done" check
Makes blk_vm_flush_all() (block_words.c) non-static and declares it in block_words.h -- it's already the entire implementation behind SAVE-BUFFERS (block_word_save_buffers() is a one-line wrapper), so sk_repl_idle() can call the exact same flush path outside word dispatch without duplicating any logic. Cheap every idle tick regardless of dirty state: every check inside is a small fixed-size scan, so no separate pre-check was needed on top of it. Caught a real bug via a live persistence test before trusting the feature: the first version gated the flush on sk_repl_get_active_vm() returning non-NULL, but NULL is that accessor's documented default (Tripod's own USE-redirect override, "restore default dispatch") -- without an active USE redirect, the flush silently no-op'd for the entire session. Confirmed live: wrote a byte via BUFFER (no UPDATE/SAVE-BUFFERS), waited past the idle cadence, killed QEMU abruptly, rebooted with the same disk image, read back 0 instead of the written 65. Fixed by threading the VM sk_repl_run()'s own loop already resolves each iteration (g_repl_active_vm ? g_repl_active_vm : vm) down as a parameter through sk_readline() into sk_repl_idle(), rather than trying to re-derive it from an accessor with the wrong default. Re-ran the same test after the fix: read back 65, matching the written byte -- the write survived an abrupt kill with no explicit flush call anywhere in the test, proving the idle-tick auto-flush genuinely ran. All three architectures re-verified clean. FABRIC-2.md Section V item 6 and the corresponding Milestone 3 punch-list item marked done. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1b80609cb0
commit
8eaefeb9ee
@@ -270,8 +270,17 @@ static vaddr_t blk_vm_assign(VM *vm, uint32_t lbn) {
|
||||
* the epoch first (Milestone 2h, see blk_vm_check_epoch()) since this
|
||||
* function walks vm->blk_vm_lbn[]/vm->blk_vm_cbuf[] directly rather than
|
||||
* through blk_vm_find() -- a stale-epoch dirty slot must be discarded, not
|
||||
* flushed onto whatever device now owns that LBN. */
|
||||
static void blk_vm_flush_all(VM *vm) {
|
||||
* flushed onto whatever device now owns that LBN.
|
||||
*
|
||||
* Non-static: this is the entire implementation behind SAVE-BUFFERS
|
||||
* (block_word_save_buffers() below is a one-line wrapper) -- exposed
|
||||
* (declared in block_words.h) so kernel-side code can reuse the exact
|
||||
* same flush path outside the word-dispatch mechanism, e.g. sk_repl_idle()
|
||||
* (see FABRIC.md/FABRIC-2.md Section V item 6). Cheap to call when
|
||||
* nothing is dirty: every check below is a small fixed-size scan
|
||||
* (BLK_VM_SLOTS here, DISK_CACHE_SLOTS per device inside blk_flush()),
|
||||
* no I/O happens unless something actually needs writing. */
|
||||
void blk_vm_flush_all(VM *vm) {
|
||||
blk_vm_check_epoch(vm);
|
||||
for (int i = 0; i < BLK_VM_SLOTS; i++) {
|
||||
if (vm->blk_vm_cbuf[i] != NULL && vm->blk_vm_dirty[i]) {
|
||||
|
||||
@@ -137,6 +137,21 @@ void mark_buffer_dirty(VM * vm);
|
||||
*/
|
||||
void save_all_buffers(VM * vm);
|
||||
|
||||
/**
|
||||
* @brief Sync every dirty VM block-window slot to the C-layer block cache,
|
||||
* then flush the whole block subsystem to physical media --
|
||||
* the complete SAVE-BUFFERS implementation (unlike
|
||||
* save_all_buffers() above, which only calls blk_flush() and so
|
||||
* misses any BUFFER-modified-but-not-yet-UPDATE'd content still
|
||||
* sitting only in vm->memory's window). Cheap to call when nothing
|
||||
* is dirty -- every check inside is a small fixed-size scan, no
|
||||
* I/O happens unless something actually needs writing. Safe to
|
||||
* call from outside word dispatch (e.g. a periodic idle-tick
|
||||
* auto-flush); vm must be non-NULL.
|
||||
* @param vm Pointer to the Forth virtual machine instance
|
||||
*/
|
||||
void blk_vm_flush_all(VM * vm);
|
||||
|
||||
/*
|
||||
* @brief Marks all buffers as empty
|
||||
* @param vm Pointer to the Forth virtual machine instance
|
||||
|
||||
Reference in New Issue
Block a user