doe_log.c: add vm_name/vm_id_hex identity columns; new calibration workload
Adds the identity columns HB-ON's existing per-tick CSV logger (doe_log_tick_row(), doe_log.c) was missing. Previously every column described *a* VM's state each row, but nothing said which VM emitted it -- concurrent VMs' rows were indistinguishable by source. Two new first columns, vm_name and vm_id_hex, resolved via a reverse lookup on vm->stadium_vm_id (capsule_vm_registry_get()). Real bug found and fixed while building this: the freestanding snprintf here silently prints the literal format string instead of substituting for %016llx (width+ll+hex unsupported) -- caught by reading the actual emitted row, not assumed to work. Replaced with a hand-rolled hex nibble-table loop, the same idiom vm_uuid_format()/ MINT-SCRATCH-EMIT already use. Corrects FABRIC-3.md's own prior "still not started: CSV driver" framing: no bespoke CSV emitter is needed for the multiuser DoE at all -- this per-tick logger already exists, fires automatically inside every VM's own execution loop, and just needed HB-ON plus these identity columns to be usable for concurrent workers. Also corrects doe_log.h's own stale doc comment claiming g_doe_log_enabled defaults to 1 -- doe_log.c's own source is authoritative: 0, off by default, matching the HB-ON/HB-OFF naming. One real, honest limitation recorded rather than smoothed over: vm_name reads blank for any tick captured during a WORKER-BIRTH'd capsule's own self-execution at birth time, since capsule_birth_baby() runs that work (and its heartbeat ticks) before the registry name can be set. vm_id_hex is unaffected (reads directly from vm->stadium_vm_id) and still uniquely disambiguates every row -- confirmed live: a blank-name row's own vm_id_hex matched its later PARITY:KILL line's vm_id exactly. New workload-calib1.4th: Bob confirmed the existing 10 workload-N.4th files aren't fixed. Sized to cross HEARTBEAT_CHECK_FREQUENCY (256 word-executions/tick) many times over while staying far lighter than RUN-FIB/RUN-CHAOS5, both too slow under TCG for a bounded verification run. A real, reusable addition, not a throwaway. Verified live on amd64 via a self-contained one-shot EXEC'd test (HB-ON, WORKER-BIRTH two calibration workers, HB-OFF, VM-ERROR? on both, KILL both, completion banner) rather than interactive polling, which breaks once HB-ON makes the log grow continuously via Hera/ Hermes/Artemis's own background ticks. Clean 3-arch qemu boot on the real committed change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
e33eb36361
commit
41918a28a4
@@ -10,13 +10,29 @@
|
||||
/**
|
||||
* doe_log.c — DoE CSV logger for the LithosAnanke kernel
|
||||
*
|
||||
* Emits 20-column CSV rows to the serial log once per heartbeat tick.
|
||||
* Each row is prefixed with a cyan [HADES][DOE ] tag so it can be
|
||||
* extracted cleanly:
|
||||
* Emits CSV rows to the serial log once per heartbeat tick. Each row is
|
||||
* prefixed with a cyan [HADES][DOE ] tag so it can be extracted cleanly:
|
||||
*
|
||||
* grep -aP '\[HADES\]\[DOE \]' qemu-amd64-*.log
|
||||
*
|
||||
* Columns (in order):
|
||||
* 0a. vm_name string — the emitting VM's own registry name
|
||||
* (reverse lookup on vm->stadium_vm_id,
|
||||
* "?" if unregistered at this tick).
|
||||
* Added 2026-09-16 for the multiuser/
|
||||
* multitasking DoE (FABRIC-3.md
|
||||
* §XXXIII): every prior column already
|
||||
* described *a* VM's state each row,
|
||||
* but nothing said *which* VM emitted
|
||||
* it, making concurrent-VM rows
|
||||
* indistinguishable by source.
|
||||
* 0b. vm_id_hex string — the emitting VM's own stadium_vm_id
|
||||
* as "hi-lo" hex, same format
|
||||
* PARITY:BIRTH/PARITY:KILL already
|
||||
* print. Names get reused across a
|
||||
* trial's own KILL+rebirth cycles;
|
||||
* this is the one column unique to a
|
||||
* single birth instance.
|
||||
* 1. tick_number uint32 — monotonic heartbeat counter
|
||||
* 2. elapsed_ns uint64 — ns since run start
|
||||
* 3. tick_interval_ns uint64 — actual interval from prior tick
|
||||
@@ -101,6 +117,7 @@ int g_doe_log_enabled = 0; /* off by default -- HB-ON to enable, per instruction
|
||||
|
||||
static const char *doe_header =
|
||||
DOE_PREFIX
|
||||
"vm_name,vm_id_hex,"
|
||||
"tick_number,elapsed_ns,tick_interval_ns,"
|
||||
"cache_hits_delta,bucket_hits_delta,word_executions_delta,"
|
||||
"hot_word_count,avg_word_heat_q48,"
|
||||
@@ -154,6 +171,38 @@ void doe_log_tick_row(VM *vm, const HeartbeatTickSnapshot *snap)
|
||||
* for values > 2^32 on aarch64 due to mixed-width varargs ABI behaviour. */
|
||||
unsigned vm_call_depth_max = (vm && vm->call_stack_max > 0) ? (unsigned)vm->call_stack_max : 0;
|
||||
|
||||
/* Identity columns (2026-09-16, FABRIC-3.md §XXXIII): reverse-lookup
|
||||
* this row's own emitting VM by its stadium_vm_id -- name can be
|
||||
* reused across a KILL+rebirth cycle, so vm_id_hex is what actually
|
||||
* disambiguates one birth instance from the next. "?" name / all-zero
|
||||
* id if vm is NULL or not (yet) registered, never a crash. */
|
||||
const char *vm_name = "?";
|
||||
char vm_id_hex[34] = "0000000000000000-0000000000000000";
|
||||
if (vm) {
|
||||
VMRegistryEntry self_entry;
|
||||
if (capsule_vm_registry_get(vm->stadium_vm_id, &self_entry) == 0) {
|
||||
vm_name = self_entry.name;
|
||||
}
|
||||
/* Hand-rolled hex, not snprintf("%016llx", ...) -- found live
|
||||
* (2026-09-16) that this freestanding snprintf doesn't support
|
||||
* width+ll+x and silently prints the literal format string
|
||||
* instead of substituting. Same nibble-table idiom vm_uuid.c's
|
||||
* own vm_uuid_format() and MINT-SCRATCH-EMIT already use. */
|
||||
{
|
||||
static const char hexd[] = "0123456789abcdef";
|
||||
uint64_t halves[2] = { vm->stadium_vm_id.hi, vm->stadium_vm_id.lo };
|
||||
int pos = 0, h;
|
||||
for (h = 0; h < 2; h++) {
|
||||
int i;
|
||||
for (i = 15; i >= 0; i--) {
|
||||
vm_id_hex[pos++] = hexd[(halves[h] >> (i * 4)) & 0xF];
|
||||
}
|
||||
if (h == 0) vm_id_hex[pos++] = '-';
|
||||
}
|
||||
vm_id_hex[pos] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t hera_heat_q48 = doe_log_heat_by_name("Hera");
|
||||
uint64_t hermes_heat_q48 = doe_log_heat_by_name("Hermes");
|
||||
uint64_t artemis_heat_q48 = doe_log_heat_by_name("Artemis");
|
||||
@@ -180,8 +229,11 @@ void doe_log_tick_row(VM *vm, const HeartbeatTickSnapshot *snap)
|
||||
|
||||
char buf[DOE_BUF_SIZE];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s,%s,"
|
||||
"%u,%llu,%llu,%u,%u,%u,%llu,%llu,%u,%u,%u,%llu,%llu,%llu,%llu,%u,%llu,%llu,%llu,%llu,%u,"
|
||||
"%llu,%u,%u,%u,%u,%u",
|
||||
vm_name,
|
||||
vm_id_hex,
|
||||
snap->tick_number,
|
||||
(unsigned long long)snap->elapsed_ns,
|
||||
(unsigned long long)snap->tick_interval_ns,
|
||||
|
||||
Reference in New Issue
Block a user