feat(v4.0.0): a node asks its kernel by a blocking write to its port
ENGINE.md step 2, the carrier. Ruled 2026-10-05 (V3-PARITY.md 1i), on DECOMPOSITION.md section 6: a write to a port blocks until the neighbour reads. - node: v4_node_port_attach, v4_node_port_served; a store to the port keeps the value as the request and blocks the node - exec: a blocked node executes nothing; served, it goes on from the opcode after the store, in the same instruction word; a fault meanwhile abandons the rest of the word - compile.v4: n KERNEL-WORD name makes a word whose body writes n to the port; its arguments and results are on the data stack - boot: the kernel's words are made by handing the node text, and requests are served between the node's opcodes; one no one serves is error 12 - BYE, the first kernel word: hosted it leaves the program, as hosted v3; on the lone node it is v3's cold restart - ENGINE.md 3a: multiuser, multitasking, preemptive and cooperative, and what that asks of the engine Verified: make -C v4 test passes at both widths, with tests/test_port.c; hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 passes POST with the same hashes as hosted, and a kernel word no one serves and BYE typed at each prompt are answered (logs/20261005-185506, -185734, -190101; -185234 is an amd64 run in which those two lines were not typed). Not done: v3's own C functions serving a node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5f1f60fc84
commit
8df6c16766
+60
-5
@@ -85,10 +85,14 @@ framebuffer words. It takes its arguments from the VM's data stack.
|
||||
*Ruled:* a node asks for a block by number and the kernel decides the
|
||||
rest; a node sends a message by asking.
|
||||
|
||||
*v4:* a kernel word is a dictionary entry on the node whose code hands a
|
||||
request to the kernel, with its arguments on the node's data stack. The
|
||||
C functions are v3's. **How the request is carried is not designed yet**
|
||||
and is the first thing step 2 settles.
|
||||
*v4, ruled 2026-10-05:* a kernel word is an ordinary dictionary entry on
|
||||
the node whose body writes its request number to the node's port. The
|
||||
write blocks the node until the kernel, its neighbour on that port, has
|
||||
served it (`DECOMPOSITION.md` section 6: "a write blocks until the
|
||||
neighbour reads"). The kernel serves between the node's opcodes, so the
|
||||
node is always stopped when C touches it; the function takes its arguments
|
||||
from the node's data stack and leaves its results there. Kernel words are
|
||||
made by handing the node text at boot. The C functions are v3's.
|
||||
|
||||
### 3.4 The stacks and the dictionary, from the kernel's side
|
||||
|
||||
@@ -129,6 +133,41 @@ engine's.
|
||||
*v3:* `vm_dict_hash_fn`, a hook the birth protocol calls. *v4:* the same
|
||||
hook, answered from the node's dictionary.
|
||||
|
||||
## 3a. Many VMs at once (Captain Bob, 2026-10-05)
|
||||
|
||||
> Do not forget that this is multiuser, multitasking, and a hybrid of
|
||||
> preemptive and cooperative.
|
||||
|
||||
And, the same day: "Hera will be the process manager via compudynamics per
|
||||
node."
|
||||
|
||||
What that asks of the engine, and what it has:
|
||||
|
||||
- **A node can be stopped between any two instruction words and gone on
|
||||
with later.** Everything a node is doing is in the node and its
|
||||
execution state; `v4_exec_step_word` runs one instruction word and
|
||||
returns. So whoever runs the nodes can take the processor from one at any
|
||||
word and give it to another: that is the preemptive half, and the engine
|
||||
already allows it. Nothing may be built that needs a node to run a line,
|
||||
or a request, to its end without interruption.
|
||||
- **A node gives way by itself when it writes to its port.** It is blocked
|
||||
until served (3.3), and while it is blocked another can run: that is the
|
||||
cooperative half.
|
||||
- **Each node has its own execution state.** The place a blocked node goes
|
||||
on from is kept per node (`v4_exec_state`), never in one shared place.
|
||||
- **Each user is a VM** (`FABRIC-2.md` D.2: "a session IS a VM"), so each is
|
||||
a node, with its own dictionary, stacks and ACL cards.
|
||||
|
||||
What is not designed: who decides which node runs next, and when. In v3
|
||||
that is the switcher, reading what kernel-Hermes publishes, at the
|
||||
checkpoint in the inner loop; the ruling makes it Hera's, by compudynamics.
|
||||
It is step 6's, and section 6 lists it as open.
|
||||
|
||||
**The loop that runs one node until its line ends** (`v4_boot_line`,
|
||||
`v4/system/boot.c`) is the lone node's and the hosted program's, where
|
||||
there is one node and nothing to share the processor with. It is not how
|
||||
the kernel will run a fleet, and goes with the lone node at step 4.
|
||||
|
||||
## 4. What was built on the detour
|
||||
|
||||
| Built 2026-10-05 | What becomes of it |
|
||||
@@ -156,6 +195,22 @@ its logs.
|
||||
2. **Asking the kernel, and the stacks from the kernel's side (3.3,
|
||||
3.4).** Settle how a request is carried. Kernel words callable from a
|
||||
node.
|
||||
**The carrier is done, 2026-10-05; the rest is not.** Ruled: a node asks
|
||||
by a blocking write to a port. Built: the port (`v4/src/node.c`,
|
||||
`v4_node_port_attach`, `v4_node_port_served`); a blocked node goes on
|
||||
from the opcode after the store, in the same instruction word
|
||||
(`v4/src/exec.c`); `KERNEL-WORD` (`v4/capsule/compile.v4`), which makes a
|
||||
word whose body writes its request number to the port; the boot makes
|
||||
the kernel's words by handing the node text, and serves requests
|
||||
(`v4/system/boot.c`). A request no one serves is error 12 on the node.
|
||||
The one kernel word so far is `BYE`, on both products: hosted it leaves
|
||||
the program, as hosted v3; on the lone node it is v3's cold restart.
|
||||
`v4/tests/test_port.c`; six builds agree; `BYE` and an unserved request
|
||||
typed at each bare-metal prompt. `logs/20261005-185506`, `-185734`,
|
||||
`-190101`.
|
||||
**Not done:** v3's own C functions serving a node. They take a `VM *`
|
||||
and use `vm_push`, `vm_pop` and, in places, the stack's fields directly;
|
||||
a node has to stand behind that `VM` record first.
|
||||
3. **A word is being executed (3.5).** The hook at `call`; the ACL's
|
||||
countdown and recheck; the word's count; `stadium_word_dispatch`.
|
||||
In-line words become calls. The per-call-target count goes.
|
||||
@@ -175,10 +230,10 @@ these, a group at a time, with POST after each.
|
||||
|
||||
| Open | Before |
|
||||
|---|---|
|
||||
| How a node's request to the kernel is carried | Step 2 |
|
||||
| How the node tells a dictionary entry from a bare address at `call` | Step 3 |
|
||||
| `EXECUTE`, which enters a word by a return | Step 3 |
|
||||
| `>R R> R@ I J LEAVE`, which cannot be called | Step 3 |
|
||||
| Who decides which node runs next, and when: Hera, by compudynamics; preemptive and cooperative | Step 6 |
|
||||
| The node's safe moment for message delivery and switching | Step 6 |
|
||||
| `PAD 42 OVER !`, a byte address given to `!` (D-1) | Step 5 |
|
||||
| Which word patrons' accounts the hosted product keeps, having no Stadium | Step 3 |
|
||||
|
||||
Reference in New Issue
Block a user