feat(v4): the mesh boot to spec -- Hera born empty in the kernel's fabric; births, kills, every node stepping together (#189)
ENGINE step 4 Phase 1, Tasks 5b-5d, and the edge cases (Captain Bob, 2026-11-13: "Build it to proper spec"; "Check for the edge cases"; "Yes, add it to v4-checks"). - v4/system/mesh.c, v4/include/v4/mesh.h: the nucleus assembled by the ROM and given to Hera as F18 cells; Hera born empty at place 0, the kernel on port 0, the console on port 1; told she is 10, in the registry, the kernel's words, FORTH-79, sealed, POST, the kernel's capsules. NODE-BORN / NODE-KILL in the owner's room. - No scheduler: v4_mesh_tell returns once the node told says how its text ended, and v4_mesh_step / v4_mesh_busy let the host step the fabric while it waits, so nodes run between lines as during them. A text left "waiting" is owed its end: the next line ends it "Interrupted" and is then run (MESH.md 7b.6). - kernel: sk_v4.c boots through the mesh; its idle steps the fabric while a node can run, and halts only when none can (#151 kept). stadium_return_quota and stadium_ops_forget on a kill. - Tests: v4/tests/test_mesh_boot.c (32 checks: the boot, births, kills, rebirth, a live number, a fault, no such node, Hera not killing herself, no room, a line too long, a node running for ever, a wait broken by the next line), run by `make -C v4 test` and under ASan+UBSan by `sanitize` (v4-checks); kernel/tests quota return; scripts/qemu_session.py births() and the edges on bare metal. - Docs: ENGINE.md 6 "who runs next" struck (settled: no scheduler); the Phase 1 plan; FABRIC-3 XLVIII.23; .claude/memory/rules.md: alpha.5 closed to new work. - Evidence: v4-checks 80 programs under the sanitizers, 0 failures; the hosted builds alike; two stopped v4-checks runs labelled STOPPED; three development amd64 boots labelled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
This commit is contained in:
+21
-3
@@ -5,9 +5,13 @@
|
||||
* the system, then its capsules are loaded, then the prompt.
|
||||
* docs/v4.0.0/MACHINE.md, NUCLEUS.md.
|
||||
*
|
||||
* The hosted binary (tools/hosted.c) and the bare-metal kernel
|
||||
* (kernel/src/v4/sk_v4.c) both call v4_boot_run and differ only in where
|
||||
* the text goes. So the two start the same way and print the same lines:
|
||||
* The hosted binary (tools/hosted.c) calls v4_boot_run: one node, which its
|
||||
* ROM brings up and which is handed its lines. The bare-metal kernel
|
||||
* (kernel/src/v4/sk_v4.c) did too, until 2026-11-13; it now boots the fabric
|
||||
* (v4/mesh.h; #189, ENGINE step 4 Phase 1): the ROM assembles the nucleus by
|
||||
* v4_boot_assemble, and Hera is born empty and given it. Corrected
|
||||
* 2026-11-13 -- this said the two "differ only in where the text goes".
|
||||
* Both print the same parity lines, in the same order:
|
||||
*
|
||||
* PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0x... (one for each blob of the system's source)
|
||||
* PARITY:V4_ROM words=N rom_hash=0x... instructions=N (the ROM, and what assembling the system cost)
|
||||
@@ -117,4 +121,18 @@ int v4_boot_line(const v4_boot *b, const char *text, unsigned len);
|
||||
/* The dictionary hash of a node started from `im`. */
|
||||
uint64_t v4_boot_dict_hash(const v4_node *n, const v4_image *im);
|
||||
|
||||
/* WHAT THE MESH BOOT SHARES (v4/mesh.h; #189). v4_boot_assemble: the node
|
||||
* `b->n` is born empty and its ROM assembles the system from its source,
|
||||
* the PARITY:V4_F18 and PARITY:V4_ROM lines printed, `b->im` completed from
|
||||
* the image record; 1, or 0 with the failure said -- what v4_boot_run does
|
||||
* first. v4_boot_capsule: the capsule `name` found in the directory, its
|
||||
* hash and signature checked as the boot checks them, a failure said; its
|
||||
* payload, or 0. And the boot's own way of printing numbers, so the mesh
|
||||
* prints the same parity lines. */
|
||||
int v4_boot_assemble(const v4_boot *b);
|
||||
uint32_t v4_boot_word_count(const v4_node *n, const v4_image *im);
|
||||
const uint8_t *v4_boot_capsule(const v4_boot *b, const char *name, uint32_t *length, uint64_t *id, uint64_t *hash);
|
||||
void v4_boot_say_dec(const v4_boot *b, uint32_t v);
|
||||
void v4_boot_say_hex(const v4_boot *b, uint64_t v);
|
||||
|
||||
#endif /* V4_BOOT_H */
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef struct {
|
||||
v4_cell dstack_reg, rstack_reg;
|
||||
v4_cell node_error;
|
||||
v4_cell heat_reg; /* HEAT-OP[0]; ANTICLOCK is 32 after it (node.h, #189) */
|
||||
v4_cell me; /* (ME): the node's number, which messages go by (v4/mesh.h, #189) */
|
||||
|
||||
/* the dictionary's two variables: DP holds HERE, a byte address, and
|
||||
* LATEST the newest word of FORTH. What lies below HERE, and LATEST,
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/* SPDX-License-Identifier: LicenseRef-Starship-1.0
|
||||
* Copyright (c) 2023-2026 Robert A. James
|
||||
*/
|
||||
/* mesh.h -- the kernel's boot of the fabric: Hera born empty, given the
|
||||
* system, and every node stepped together. docs/v4.0.0/MESH.md 9,
|
||||
* MACHINE.md 3; #189, ENGINE step 4 Phase 1, Task 5b (Captain Bob,
|
||||
* 2026-11-13: "Build it to proper spec").
|
||||
*
|
||||
* There is no scheduler (JUSTIFICATION.md 4: "There is no scheduler to
|
||||
* write"): every awake node executes an instruction word at each step of
|
||||
* the fabric (fabric.h), and a node with nothing to do waits at a port.
|
||||
*
|
||||
* THE BOOT, as v4/tests/test_host_unit.c does it on the host:
|
||||
* 1. the nucleus: the machine's ROM assembles the system's source on a
|
||||
* node of its own (v4/boot.h, v4_boot_assemble), and the system, as
|
||||
* assembled, is a capsule of F18 cells -- a node that is born is given
|
||||
* assembled code, never the source (Captain Bob, 2026-10-15);
|
||||
* 2. Hera is born empty at place 0, with the machine's ROM: the kernel is
|
||||
* on her port 0 -- it gives her the nucleus a cell at a time, and takes
|
||||
* her requests: blocks, the kernel's words, the registry (manage.h) --
|
||||
* and the console on her port 1, which speaks whole messages;
|
||||
* 3. she is told she is node 10 and where the console is, entered in the
|
||||
* registry, made the kernel's words, given FORTH-79, sealed, POSTed,
|
||||
* given the kernel's capsules, and sealed;
|
||||
* printing the same parity lines as v4_boot_run (boot.h).
|
||||
*
|
||||
* A NODE IS BORN (NODE-BORN): in storage the owner gives, with a mesh
|
||||
* node's ROM, the kernel on its port 0 for its blocks; it is given the
|
||||
* nucleus by whoever birthed it (centre.4th). NODE-KILL gives the storage
|
||||
* back.
|
||||
*
|
||||
* Nothing here uses the C library. The owner supplies all the memory.
|
||||
*/
|
||||
#ifndef V4_MESH_H
|
||||
#define V4_MESH_H
|
||||
|
||||
#include "v4/boot.h"
|
||||
#include "v4/blocks.h"
|
||||
#include "v4/fabric.h"
|
||||
#include "v4/manage.h"
|
||||
|
||||
#define V4_MESH_HERA 10 /* Hera's number, as the host mesh numbers her */
|
||||
#define V4_MESH_CONSOLE 1 /* the console's number as a sender, and her port to it */
|
||||
#define V4_MESH_NUCLEUS_CELLS (2u * V4_NODE_WORDS + 64u)
|
||||
|
||||
typedef struct v4_mesh v4_mesh;
|
||||
struct v4_mesh {
|
||||
/* ---- the owner's: set before v4_mesh_boot ---- */
|
||||
v4_place *places; /* the fabric's room: `capacity` places */
|
||||
unsigned capacity;
|
||||
v4_wire_queue *queues; /* the wires' memory (fabric.h): two for every wire at once */
|
||||
unsigned queue_count;
|
||||
v4_manage_entry *reg; /* the registry: `capacity` entries */
|
||||
v4_blocks *blocks; /* each place's block window, kept by the kernel: `capacity` of them */
|
||||
v4_fabric_node *nucleus; /* where the ROM assembles the system: a node of its own */
|
||||
v4_fabric_node *hera; /* Hera's storage */
|
||||
v4_device *kernel; /* the kernel on each place's port 0: `capacity` of them */
|
||||
/* storage for a node to be born, or 0: none; and given back */
|
||||
v4_fabric_node *(*room)(void *self);
|
||||
void (*unroom)(void *self, v4_fabric_node *x);
|
||||
/* a node has been born at `place`, numbered `number` once it is told; is gone (may be 0) */
|
||||
void (*born)(void *self, unsigned place);
|
||||
void (*gone)(void *self, unsigned place);
|
||||
/* a node the asker birthed has its system: its parity (may be 0) */
|
||||
void (*parity)(void *self, unsigned place, v4_cell number, const v4_node *n);
|
||||
/* the console, the keyboard, the kernel's words and capsules: as v4_boot's (boot.h) */
|
||||
void (*out)(const char *text, unsigned len);
|
||||
int (*key)(void);
|
||||
const char *const *words;
|
||||
unsigned word_count;
|
||||
void (*serve)(v4_node *n, unsigned request);
|
||||
const char *const *capsules;
|
||||
unsigned capsule_count;
|
||||
v4_image *im; /* the map's description (v4_map_image), which the boot completes */
|
||||
void *self;
|
||||
|
||||
/* ---- the mesh's own ---- */
|
||||
v4_fabric f;
|
||||
v4_manage m;
|
||||
unsigned hera_place;
|
||||
v4_cell cells[V4_MESH_NUCLEUS_CELLS]; /* the nucleus as a capsule of F18 cells */
|
||||
unsigned cell_count, given; /* how many; how many given to Hera */
|
||||
unsigned reading_nucleus[64]; /* by place: the next nucleus cell a CAPSULE-CELL gives; 0: not open */
|
||||
unsigned dones; /* how many texts have said how they ended, ever */
|
||||
v4_cell done_from, done_how; /* the last of them: from which node, and how */
|
||||
v4_cell owed_from; /* a node told texts that were left "waiting" ... */
|
||||
unsigned owed; /* ... and how many of their ends are still to come */
|
||||
};
|
||||
|
||||
/* The boot: the nucleus, Hera, her system, POST. 1, Hera asleep at her
|
||||
* wires waiting for a line; or 0, the failure printed. */
|
||||
int v4_mesh_boot(v4_mesh *ms);
|
||||
|
||||
/* Text for node `node`, from the console, and the fabric stepped until that node says how the text
|
||||
* ended: what any node prints goes to `out`; returns how it ended (V4_TEXT_*), or
|
||||
* V4_BOOT_LINE_STOPPED / _TOO_LONG / _REFUSED / _NO_INPUT (boot.h). Other nodes may run on after it
|
||||
* returns (v4_mesh_step). V4_BOOT_LINE_WAITING: Hera is asleep awaiting an answer that has not come
|
||||
* -- nothing else can run, or other nodes have run a long while and not given it; the next text from
|
||||
* the console breaks the wait (MESH.md 7b.6), and if the answer comes first, `dones` says so. */
|
||||
int v4_mesh_tell(v4_mesh *ms, v4_cell node, const char *text, unsigned len);
|
||||
|
||||
/* One step of the fabric, as the host's idle: every awake node executes an instruction word, and what
|
||||
* comes back to the console is printed (or counted, for how a text ended: `dones`). Returns how many
|
||||
* instructions were retired. The host calls it while it waits, whenever v4_mesh_busy says a node can
|
||||
* run: every node steps together, between lines as during them. */
|
||||
unsigned v4_mesh_step(v4_mesh *ms);
|
||||
int v4_mesh_busy(const v4_mesh *ms);
|
||||
|
||||
/* The node numbered `number`, or 0. */
|
||||
v4_fabric_node *v4_mesh_node(const v4_mesh *ms, v4_cell number);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user