feat(v4.0.0): step 6e -- a node removed at any step leaves the rest at rest; written up
test_host_mesh.c, 220 checks: three exchanges on the row of three -- text from the console for node 12 with what it prints and how it ended; node 11 SENDing node 12 text and waiting for its answer; a message node 12 has no way for and its NACK to node 10 -- are each played once for every engine step they take with node 11 removed at that step, and again with node 12: 17,642 removals at 64 bits. Every node left comes to rest asleep, blocked at no port and in no operation, and answers. What is typed is a word defined beforehand, so that the steps are the exchange's and not the dictionary being searched. Removed from the engine, nothing using them: v4_fabric_interrupt_error, a device's pending hook, v4_node_words_since_look, V4_ERROR_INTERRUPTED. MESH.md: 4.1's table has the addresses after the ports; 7a and 7b say what of them still holds; 7b.7's limit is closed; step 6e is written up. v4/README.md likewise. make -C v4 test and sanitize at both widths, hosted-check, lint. Three bare-metal boots with the typed session and a loop printing 400 numbers: logs/20261013-165124 (amd64), -165428 (aarch64), -165818 (riscv64). POST 538 of 538, word_count=317, dict_hash=0x0951d7e02e251554 on all six, and the three sessions are the same character for character. The boots were built with the working tree's uncommitted change to kernel/Makefile that adds the ISA to the kernel's version line; nothing else differs from this commit. The plan's final review is not done yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ab96a9f2be
commit
06da5700bc
+119
-4
@@ -104,6 +104,19 @@ word address `base`:
|
||||
| `base` … `base + V4_PORTS − 1` | Port 0 … port `V4_PORTS − 1` |
|
||||
| `base + V4_PORTS` | Any port: a read here takes from whichever port has a neighbour writing |
|
||||
| `base + V4_PORTS + 1` | Which port the last read from "any" came from. Read only. |
|
||||
| `base + V4_PORTS + 2` | Which ports have a neighbour waiting to write to this node, a bit to a port. Read only. (Section 7a.) |
|
||||
| `base + V4_PORTS + 3` | Which have one waiting to read from it; and, in the bits above those, which have anything on them at all. Read only. (Section 7a.) |
|
||||
| `base + V4_PORTS + 4` | Wire: the port that a whole-message operation is about (section 7d.3) |
|
||||
| `base + V4_PORTS + 5` | A: a value the operation needs |
|
||||
| `base + V4_PORTS + 6` | B: a second |
|
||||
| `base + V4_PORTS + 7` | Do: the number of the operation; storing it does the operation |
|
||||
| `base + V4_PORTS + 8` | How it went. Read only. |
|
||||
| `base + V4_PORTS + 9` | Which wires have a message waiting, a bit to a port. Read only. |
|
||||
|
||||
The first two rows after "which port" are for words written and read one at
|
||||
a time; the six after them are for whole messages, which is how nodes talk
|
||||
to each other since step 6e (section 7d). Words one at a time are still
|
||||
how a newborn node is sent its nucleus and how a node asks its kernel.
|
||||
|
||||
- **A write to a port blocks the node until the neighbour has read it.**
|
||||
Built 2026-10-05 for one port; the opcode after the write runs when the
|
||||
@@ -159,6 +172,12 @@ time passing for all of them at once.
|
||||
a word when the node reads, each able to say "not yet". The console, a
|
||||
disk, and the kernel that serves a node's requests (`ENGINE.md` 3.3) are
|
||||
devices.
|
||||
- **The wires' queues** (step 6e, section 7d.2). Each wire between two
|
||||
nodes, or a node and a device that speaks whole messages, has a queue of
|
||||
messages each way, in memory the fabric's owner gives it
|
||||
(`v4_fabric_queues`). A device puts and takes whole messages through the
|
||||
fabric (`v4_fabric_device_put`, `v4_fabric_device_take`). The kernel's
|
||||
port has none (7d.5).
|
||||
- **A step.** Every node that is awake and not blocked executes one
|
||||
instruction word. Then every write that has a reader waiting on the
|
||||
other end of its wire is handed over, and both nodes are unblocked. That
|
||||
@@ -240,9 +259,17 @@ and these tables. Nothing else changes.
|
||||
|
||||
## 7a. Two neighbours writing to each other (ruled 2026-10-06)
|
||||
|
||||
*(The wait of section 7c was to replace the lower-number rule and the
|
||||
looking again of this section. It was backed out on 2026-10-08; this
|
||||
section is what the code does.)*
|
||||
*(**A record since step 6e, 2026-10-13.** Messages now wait on the wires
|
||||
(section 7d) and a node writes none a word at a time, so two neighbours
|
||||
can no longer block each other and nothing below is needed to prevent it.
|
||||
What does not hold any more: looking before writing and `(GATE)`; the
|
||||
lower-number rule; the ring of messages waiting, `(MQ)`. What still
|
||||
holds: the two status addresses are in the engine and tested there
|
||||
(`v4/tests/test_fabric.c`), though the nucleus does not use them;
|
||||
`NEIGHBOUR` stays, because it is how a node knows who its centre is and
|
||||
so whose GONE to believe (7b.4); and `(LOST)` still counts what a node
|
||||
lets go. The cost at the end of this section is now 7d.6's: a message for
|
||||
a full wire is refused at once and its sender told.)*
|
||||
|
||||
The fault is in section 10, step 4. **Ruled: a node writes only to a
|
||||
neighbour that is already reading; a node keeps the messages it takes in
|
||||
@@ -299,6 +326,20 @@ kernel-Hermes's work in v3 and is not decided for the mesh.
|
||||
|
||||
## 7b. Refusals and waits (ruled 2026-10-07)
|
||||
|
||||
*(**What of this section holds since step 6e, 2026-10-13.** It holds: the
|
||||
two messages, NACK and GONE (7b.2); that a message is passed on by at
|
||||
most 16 nodes, and that there is no NACK for a NACK (7b.3); what a node
|
||||
does when it is sent a NACK or a GONE, and the endings of `AWAIT` in
|
||||
errors 19, 20 and 21 (7b.4); Hera's table and `KILL` (7b.5); and a line
|
||||
from the console ending an `AWAIT` (7b.6). It does not hold: a node no
|
||||
longer notes a NACK it owes and pays it later, because it keeps nothing:
|
||||
the NACK is put on the wire at once or counted in `(LOST)` (7d.4); no
|
||||
room is kept in a node for NACK and GONE, there being no queue in a node;
|
||||
what ends a wait is looked for on the wires, not among messages a node
|
||||
has taken in; and the blocked write of 7b.6 cannot happen. The limit of
|
||||
7b.7, that a stuck node holds up its neighbours, is closed: 7d.6 says
|
||||
what the limits are now.)*
|
||||
|
||||
**The rule of this section (reworded 2026-10-07, after the review of step
|
||||
6c): a node is never left waiting, or going round, on a node that is
|
||||
gone; and a wait on a node that is alive and stuck is ended by Hera's
|
||||
@@ -430,6 +471,11 @@ Two types, beside text (1), output (2) and done (3):
|
||||
it: it gives that message up and goes on to read the line. Only on the
|
||||
first word, so that half a message is never left on a wire
|
||||
(`v4_fabric_interrupt_error`, `v4/include/v4/fabric.h`).
|
||||
*(Removed at step 6e, 2026-10-13: no node writes a message a word at a
|
||||
time, so none is blocked writing one. `v4_fabric_interrupt_error`, a
|
||||
device's `pending` and `v4_node_words_since_look` are gone from the
|
||||
engine. Hera can be typed to whatever any node is doing:
|
||||
`v4/tests/test_host_unit.c`.)*
|
||||
- **A node waiting to write to a neighbour that has been removed** is told:
|
||||
the word that says which neighbours are reading also says which ports
|
||||
have anything on them at all, and with nothing there the wait ends in
|
||||
@@ -437,6 +483,12 @@ Two types, beside text (1), output (2) and done (3):
|
||||
|
||||
### 7b.7 Limits
|
||||
|
||||
*(**Closed at step 6e, 2026-10-13**, but for the last of these, which
|
||||
stands. A node that is stuck holds up no other node, and neither does
|
||||
one that is asleep: what is for it waits on its wire. A node that waits
|
||||
for an answer passes on what is for other nodes while it waits. What a
|
||||
stuck node costs now is in section 7d.6.)*
|
||||
|
||||
- The room kept for NACK and GONE is finite, and so is the list of NACKs
|
||||
a node owes. Past them one is dropped and counted in `(LOST)`. A sender
|
||||
left waiting by that is ended as any stuck wait is: by Hera, or from the
|
||||
@@ -1612,7 +1664,70 @@ Each is tested, committed and pushed before the next.
|
||||
and `-06*` are of the wait as built and are kept as its record.
|
||||
|
||||
**6e. Messages on the wire (section 7d).** Ruled 2026-10-08: the
|
||||
second attempt at 6d. Not built.
|
||||
second attempt at 6d. **Built and verified 2026-10-13; its final
|
||||
review is still to come** (last item below).
|
||||
- *The wire* (`v4/include/v4/wire.h`, `v4/src/wire.c`, `d5cd6460`,
|
||||
`83694b18`): a queue of whole messages, one way; put, look, take,
|
||||
move and drop, each all or nothing. `v4/tests/test_wire.c`, 112
|
||||
checks.
|
||||
- *The engine* (`v4/src/node.c`, `v4/src/fabric.c`): the six addresses
|
||||
of 7d.3 and the ten operations; the wires' queues given by the
|
||||
fabric's owner; a device that puts and takes whole messages; the
|
||||
kernel's port, which has no queue. `v4/tests/test_fabric.c`, 306
|
||||
checks.
|
||||
- *The nucleus* (`v4/capsule/core.v4`, `quit.v4`, `b1d09af0`): `(DO)`,
|
||||
`(WAY)`, `(ROOM?)`, `(SERVE)`, `(REFUSE)`; `(IDLE)`, `SEND`, `AWAIT`,
|
||||
printing and how text ended, all on the wires. `(MQ)`, `(GATE)`, `(OWE)` and
|
||||
`(PAY)` are gone.
|
||||
- *The hosts* (`v4/system/boot.c`, which both products' lone node is
|
||||
run by, and the tests' consoles) speak whole messages.
|
||||
- *Two reviews of the nucleus, each mended* (`6a7d0aa2`, `f1419e73`):
|
||||
7d.3 and 7d.4 carry what they changed, marked "fix round".
|
||||
- *A node removed at every step* (acceptance 6):
|
||||
`v4/tests/test_host_mesh.c`, 220 checks. Three exchanges on the row
|
||||
of three -- text from the console for node 12, what it prints and how
|
||||
it ended; node 11 `SEND`ing node 12 text and waiting for its answer;
|
||||
a message node 12 has no way for, and its NACK to node 10 -- are each
|
||||
played whole, and then once for every engine step they take (3,579,
|
||||
4,214 and 1,025 at 64 bits) with node 11 removed at that step, and
|
||||
again with node 12: 17,642 removals. After each, every node left came
|
||||
to rest asleep, blocked at no port and in no operation, and answered
|
||||
`1 2 + .`; with node 11 gone, node 12 is wired to node 10 first, as
|
||||
whoever removed it would, so that it can be asked. None failed. The
|
||||
test was shown to fail, in 4,376 of them, with the engine changed so
|
||||
that a wait for room on a cut wire never ends.
|
||||
*What is typed in that test is a word defined beforehand, not a line
|
||||
of several words:* a line is mostly the dictionary being searched,
|
||||
tens of thousands of steps in which no message moves, and each would
|
||||
be a removal played to its end. The first exchange as the line
|
||||
`7 8 * .` takes 38,234 steps; removal was tried at its first 300 and
|
||||
none failed, and it is not in the suite.
|
||||
- *Removed from the engine, nothing using them:*
|
||||
`v4_fabric_interrupt_error`, a device's `pending`,
|
||||
`v4_node_words_since_look`, and `V4_ERROR_INTERRUPTED` (the nucleus
|
||||
raises error 21 itself). A device's `take` and `give`, and the two
|
||||
status addresses of 7a, stay: the kernel's port and the engine's own
|
||||
tests use them.
|
||||
- *Other tests.* `v4/tests/test_host_unit.c`, 81 checks (Hera and
|
||||
four); `v4/tests/test_host_depth.c`, 397 checks (acceptance 7 on the
|
||||
mesh); `v4/tools/depthsweep.py`, 230 runs on the hosted product.
|
||||
- *Verified.* `make -C v4 test` and `sanitize` at both widths,
|
||||
`hosted-check`, and `mkcapsule --lint capsules/`: no failures. Three
|
||||
bare-metal boots, `logs/20261013-165124` (amd64), `-165428`
|
||||
(aarch64), `-165818` (riscv64), each typing the session of step 6d's
|
||||
last boots and a loop that prints 400 numbers: 29 values on a line
|
||||
("Stack overflow"); `WORDS` with 26 on the stack; `AWAIT` with 27,
|
||||
and `5 AWAIT` ended by the next line ("Interrupted"); all 400
|
||||
numbers, in order. On all six systems: POST 538 of 538,
|
||||
`word_count=317`, `dict_hash=0x0951d7e02e251554`; and what the three
|
||||
boots answered at the prompt is the same, character for character.
|
||||
- *Seen in the older logs, and not a fault of the node.* In the boots
|
||||
of 2026-10-08 `WORDS` shows a character twice here and there on
|
||||
amd64 and riscv64 (`LOG-INFFO-STR`, `QQ.-`). The script that typed
|
||||
those sessions read QEMU's serial socket only between lines; with
|
||||
the socket read as it comes, as these three were, there is none.
|
||||
- **Not done:** the final review of the whole step by a fresh
|
||||
reviewer (the plan's last step).
|
||||
|
||||
7. **A second unit; scaling while running; sleep, wake and kill by
|
||||
command.**
|
||||
|
||||
Reference in New Issue
Block a user