From 482cc75faf3783ff44415fda2e549e54f62c41ee Mon Sep 17 00:00:00 2001 From: rajames Date: Wed, 7 Oct 2026 23:38:07 -0400 Subject: [PATCH] feat(v4.0.0): every message begins through the wait -- a stuck node holds up no one (GATE) offers a message's first word and sleeps until it is taken, taking in whatever is written to the node meanwhile; (PAY) offers every refusal owed at once, one to a port; a node that owes one sleeps in the wait. Writing without looking, looking again and again, and the lower-number rule are gone. Text from the console for a node whose own text waits to begin a message ends that text Interrupted. The lone node's hosts serve an offer as a write. MESH.md 7c; plan step 6d task 2. Co-Authored-By: Claude Opus 5.5 --- capsules/v4/nucleus-64.f18 | Bin 56608 -> 56784 bytes v4/capsule/core.v4 | 170 +++++++++++++++++++++---------------- v4/capsule/quit.v4 | 22 ++--- v4/system/boot.c | 1 + v4/tests/host_map.h | 9 +- v4/tests/test_host_mesh.c | 90 +++++++++++++++----- v4/tests/test_host_quit.c | 1 + v4/tests/test_host_unit.c | 8 +- 8 files changed, 188 insertions(+), 113 deletions(-) diff --git a/capsules/v4/nucleus-64.f18 b/capsules/v4/nucleus-64.f18 index 72c8fb8fb2a82cc653ee804af68cc67001f6229e..2622e49267794d6df9dd9ce4b06ff505fe429ed9 100644 GIT binary patch literal 56784 zcmb__34B$>_5aPw0tpyEkk!`bRzVG$RRIwavOqK>AqktbDgpv3$u$H;MTsqSK?>4p zUBOgwk4qI5ElNOCr1}KKty-lOEACN(xWa$VobUI(cL$!){{HuqPtKc}v(1?^XXeh# zz1M$d^GMHJ9p#_7=J!(Q$BOgiSL)c&M{17#Cm!?4e|^-;@;e0?gbfeeyG62wBft6R zIiJhV_47`+RNz5g)0+bQSf3{Zk}e8W{Mg_%l7EP|_%nfrd1+4xH2D@^e#_O{%eLkI zsY`7+`52|GsxJPP(qmo}x~VH@g!t-q_h*nO`_*72S< zNZ<)x_LBmKK<;2~vDN1UFU{r~{tB~a#01Y-2*9eA+t^cukumf9k>^Rs!(}O~2kK<*MzTJw}f9$8443 z$6mK_XZm2l^1M62zj=2jttSY(quh_pS|@mS1J94u*!urfLV&r9{VYHEEm!@{&9**g zg1-KyS8V#hfc}J#ocp|7qoVLpe+=r8t#)Smldn|oD)4>GTV(lcH-SK|$G!ETI5puo z&2L=tj@6HJm8@6xFGKeGq(%9UMfuYX|7Tj^Pdb-B+rj_)FdMJW2LCrwzEjMe zp!fUexXy8f_)#aH{QcMkcM9)$3pR`u$b8B*?Qx;x^NKz(%-WrPG=l9@y7^ndVSDsV z(ebQrN_aeDd)x%S>mRR=^;7y|IqK8AbBy&%+L8W9Kh1-DH=laB`T0rk3zFm)CdsFL zT>c{+{IZn#=fy65EFAYt|0$RJl9V8hwo$yn)-T7V)IYB2Fr6QJ-nP@Yz-~HUV;o?A zVSjI2qVa)tq8({J+NlM8+crh}dwcMoyG8x{d-(Ym^!L(E<3vC9hjY+gQhB(A;|Jr? zern`cyZcXRysZYm-=lm^ipGn1h}X0uA?Mwat=dUDu)#|ZFF&wWfP0

^7mt! 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 F{{sLEi$4GW literal 56608 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 z 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, b->h); if (n->stopped) return V4_BOOT_LINE_STOPPED; + (void)v4_node_offer_as_write(n); /* in the wait (MESH.md 7c): what it offers is a write, here where whatever is on a port takes at once */ if (n->asking && n->ask_port == KERNEL_PORT) { /* a request: the kernel's turn */ if (v4_blocks_serve(&boot_blocks, n, n->request)) { /* a block, as for any node */ diff --git a/v4/tests/host_map.h b/v4/tests/host_map.h index 5899f0e8..3cd861a7 100644 --- a/v4/tests/host_map.h +++ b/v4/tests/host_map.h @@ -87,6 +87,8 @@ #define MQ_TAIL (BUF0_W - 36) /* where the next will go, */ #define MQ_COUNT (BUF0_W - 37) /* and how many cells they take */ #define AWAIT_FROM (BUF0_W - 39) /* the node whose word of how text ended is waited for */ +#define GATE_WORD (BUF0_W - 32) /* the first word of a message that is being offered */ +#define PAY_K (BUF0_W - 123) /* for each port, which refusal owed is offered there, counted from 1; 0: none. V4_PORTS cells */ #define GATE_PORT (BUF0_W - 38) /* the port address a message is about to be begun on */ #define NEAR (BUF0_W - 64) /* for each port, the number of the node on the other end; 0: not told */ #define MQ_HDR (BUF0_W - 56) /* a message being taken in: its seven words and the port it came on */ @@ -125,7 +127,7 @@ typedef char host_map_ports_fit[(V4_PORTS <= 8u) ? 1 : -1]; /* the messages waiting are above the dictionary */ typedef char host_map_queue_fits[(MQ_W >= DICT_END_W) ? 1 : -1]; /* the ports, with the offers and the wait after them, end below the cells that follow */ -typedef char host_map_port_block_fits[(PORT + 2 * (v4_cell)V4_PORTS + 5 <= BUF0_W - 115) ? 1 : -1]; +typedef char host_map_port_block_fits[(PORT + 2 * (v4_cell)V4_PORTS + 5 <= PAY_K && PAY_K + (v4_cell)V4_PORTS <= BUF0_W - 115) ? 1 : -1]; /* How many slots, from slot 0, a branch may sit in on a node this size: those * whose address field reaches every word of it. */ @@ -198,6 +200,11 @@ static int host_load(v4_text *tx, v4_node *n, const char *const *files, unsigned v4_text_constant(tx, "-PORTS", -(v4_cell)V4_PORTS); v4_text_constant(tx, "(NEAR)", NEAR); v4_text_constant(tx, "(GATE-PORT)", GATE_PORT); + v4_text_constant(tx, "(GATE-WORD)", GATE_WORD); + v4_text_constant(tx, "(PAY-K)", PAY_K); + v4_text_constant(tx, "PORTS-1", (v4_cell)V4_PORTS - 1); + v4_text_constant(tx, "(OFFER)", PORT + (v4_cell)V4_PORT_OFFER); + v4_text_constant(tx, "(WAIT)", PORT + (v4_cell)V4_PORT_WAIT); v4_text_constant(tx, "(AWAIT-FROM)", AWAIT_FROM); v4_text_constant(tx, "(MQ)", MQ_W); v4_text_constant(tx, "(MQ-END)", MQ_W + MQ_CELLS); diff --git a/v4/tests/test_host_mesh.c b/v4/tests/test_host_mesh.c index cde5eaa7..7a86554c 100644 --- a/v4/tests/test_host_mesh.c +++ b/v4/tests/test_host_mesh.c @@ -112,6 +112,10 @@ static unsigned starforth_node(unsigned k) return (unsigned)id; } +/* The same, answering with what has been printed: for when a node is + * spinning and the fabric never comes to rest. */ +static const char *said(v4_cell node, const char *text) { (void)tell(node, text); return printed; } + static int waiting(unsigned id) { const v4_node *n = &v4_fabric_node_at(&f, id)->n; @@ -364,9 +368,10 @@ int main(void) { CHECK(is_empty(tell(11, "0 GOT !")) && is_empty(tell(11, "12 AWAIT .")) && pool[1].n.mem[AWAIT_FROM] == 12, "node 11 waits on 12 again"); CHECK(is_empty(tell(10, ": F40 40 0 DO S\" HIT\" 11 SEND LOOP ; F40")) && pool[1].n.mem[OWED_COUNT] == 0, "node 10 sends it as many messages as it has room for"); - (void)tell(10, ": ONE S\" HIT\" 11 SEND 12 NO-ROUTE 12 11 GONE 11 AWAIT . ; ONE"); + /* node 11 does what it has kept before it pays what it owes (7b.3): forty answers come first */ + (void)tell(10, ": ONE S\" HIT\" 11 SEND 12 NO-ROUTE 12 11 GONE 41 0 DO 11 AWAIT DROP LOOP ; ONE"); CHECK(strstr(printed, "Message refused") != NULL && pool[0].n.mem[AWAIT_FROM] == 0, - "it sends one more, for which there is no room, ends node 11's wait, and waits for node 11's answer: its own wait ends, the message refused: \"%s\"", printed); + "it sends one more, for which there is no room, ends node 11's wait, and waits for node 11's answers: after the forty, its wait ends, the message refused: \"%s\"", printed); CHECK(strtol(tell(11, "GOT @ ."), NULL, 10) == 40 && is_empty(tell(10, "12 3 ROUTE")) && is_empty(tell(11, "12 3 ROUTE")), "node 11 did the forty it had kept; the ways are told again"); } @@ -393,34 +398,75 @@ int main(void) CHECK(is_empty(tell(10, "66 NO-ROUTE")) && waiting(hera) && waiting(mid) && waiting(far), "the way is forgotten, and all three are at rest"); } - /* a node that owes a refusal to a node that is stuck is not stuck itself */ - CHECK(is_empty(tell(12, "NO-ROUTES 1 3 ROUTE 10 3 ROUTE 11 2 ROUTE")) && is_empty(tell(11, "55 3 ROUTE")), "node 12 has no way for 55; node 11 is told the way to 55 is by node 12"); + /* ---- a node that is stuck holds up no one (MESH.md 7c) ------------------- */ + v4_fabric_gone_error(&f, V4_ERROR_NO_ONE); + + /* From here a node is spinning, so the fabric never comes to rest: said() + * is tell(), answering with what was printed by the time it gave up. */ + + /* a refusal owed to a stuck node whose number is the lower */ + CHECK(is_empty(said(12, "NO-ROUTES 1 3 ROUTE 10 3 ROUTE 11 2 ROUTE")) && is_empty(said(11, "55 3 ROUTE")), "node 12 has no way for 55; node 11 is told the way to 55 is by node 12"); CHECK(strcmp(tell(11, ": C1 S\" 1 DROP\" 55 SEND BEGIN 0 UNTIL ; C1"), "(still running)") == 0, "node 11 sends 55 a message and is then stuck in a loop"); CHECK(pool[2].n.mem[OWED_COUNT] == 1, "node 12 owes node 11 a refusal, and cannot give it: node 11 is not reading"); - (void)tell(12, "7 8 * ."); - CHECK(strcmp(printed, "56 ") == 0 && printed_from == 12, "node 12 goes on doing what it is sent: \"%s\"", printed); + CHECK(strcmp(said(12, "7 8 * ."), "56 ") == 0 && printed_from == 12, "node 12 goes on doing what it is sent: \"%s\"", printed); + { + v4_uheat_t clock = pool[2].es.anticlock; + unsigned k; + for (k = 0; k < 1000; k++) (void)v4_fabric_step(&f); + CHECK(v4_node_in_wait(&pool[2].n) && pool[2].es.anticlock == clock && pool[2].n.mem[OWED_COUNT] == 1, "between times it sleeps in the wait, still owing, and executes nothing"); + } + CHECK(strcmp(said(10, ": X12 S\" 66 EMIT\" 12 SEND ; X12"), "B") == 0 && printed_from == 12, "another node writes to it and is answered: \"%s\"", printed); - /* a node that is waiting to write to a node finds out when that node is removed */ - (void)tell(12, ": TO11 S\" 1 DROP\" 11 SEND 65 EMIT ; TO11"); - CHECK(ended == 0, "node 12 sends node 11 a message: node 11 is not reading, and node 12 waits to write to it"); + /* two refusals owed: one to the stuck node, one to a node that waits for it */ + CHECK(is_empty(said(10, "77 3 ROUTE")), "node 10 is told the way to 77 is by node 12, which has none"); + CHECK(strstr(said(10, ": W77B S\" 1 DROP\" 77 SEND 77 AWAIT . ; W77B"), "Message refused") != NULL && pool[0].n.mem[AWAIT_FROM] == 0 && pool[2].n.mem[OWED_COUNT] == 1, + "node 10 sends 77 a message and waits: node 12, which still owes the stuck node, tells node 10 it was refused: \"%s\"", printed); + CHECK(is_empty(said(10, "77 NO-ROUTE")), "the way is forgotten"); + + /* a line that must begin a message to the stuck node waits, and the node takes in what comes */ + CHECK(is_empty(said(10, ": TO11 S\" 1 DROP\" 11 SEND 65 EMIT ; TO11")) && ended == 0 && v4_node_in_wait(&pool[0].n) && !pool[0].n.asking, + "node 10 sends the stuck node a message: its line waits in the wait, not blocked writing"); + { + v4_cell kept = pool[0].n.mem[MQ_COUNT]; + CHECK(is_empty(said(12, "7 8 * .")) && ended == 0 && pool[0].n.mem[MQ_COUNT] > kept && v4_node_in_wait(&pool[0].n), + "text from the console for node 12 comes to node 10: it keeps it, and its line goes on waiting"); + } + { + const char *r = said(10, "66 EMIT"); + CHECK(strstr(r, "Interrupted\n") != NULL && strstr(r, "A") == NULL && strstr(r, "B") != NULL && strstr(r, "Interrupted\n") < strstr(r, "B"), + "text from the console for node 10 itself ends the line that waited, with an error that says so, and is then done: \"%s\"", r); + CHECK(strstr(r, "56 ") != NULL && ended == 3, "and what it kept for node 12 is passed on and done: \"%s\", %d ended", r, ended); + } + + /* the stuck node is removed while a line waits to begin a message to it */ + CHECK(is_empty(said(10, "TO11")) && ended == 0 && v4_node_in_wait(&pool[0].n), "node 10's line waits on the stuck node again"); CHECK(v4_fabric_remove(&f, mid) == &pool[1], "node 11 is removed"); - (void)tell(10, "1 DROP"); - CHECK(strstr(printed, "No one on that port") != NULL && strstr(printed, "A") == NULL, "node 12's line ends in an error that says no one is there: \"%s\"", printed); + { + unsigned k; + for (k = 0; k < 200000 && ended == 0; k++) (void)v4_fabric_step(&f); + CHECK(strstr(printed, "No one on that port") != NULL && strstr(printed, "A") == NULL && ended == 1, "the line ends in an error that says no one is there: \"%s\"", printed); + } step_cap = 20000000; - CHECK(strcmp(tell(12, "7 8 * ."), "56 ") == 0 && pool[2].n.mem[OWED_COUNT] == 0 && waiting(far) && waiting(hera), - "it goes on, the refusal it owed node 11 let go: it owes nothing and is at rest"); + CHECK(strcmp(said(12, "7 8 * ."), "56 ") == 0 && pool[2].n.mem[OWED_COUNT] == 0 && waiting(far) && !v4_node_in_wait(&pool[2].n) && waiting(hera), + "node 12 goes on, the refusal it owed node 11 let go: it owes nothing and is at rest"); - /* THE LIMIT (MESH.md 7b.7): a refusal owed to a neighbour whose number is the higher is written - * without looking, as any message to it is, so a node that is stuck holds up a neighbour that owes - * it one -- until it is removed */ + /* a refusal owed to a stuck node whose number is the higher */ step_cap = 3000000; - CHECK(is_empty(tell(12, "55 3 ROUTE")), "node 12 is told the way to 55 is by node 10, which has none"); - CHECK(strcmp(tell(12, ": C2 S\" 1 DROP\" 55 SEND BEGIN 0 UNTIL ; C2"), "(still running)") == 0 && pool[0].n.asking && pool[0].n.mem[OWED_COUNT] == 1, - "node 12 sends 55 a message and is then stuck in a loop: node 10 owes it a refusal, writes it, and is blocked"); - v4_fabric_gone_error(&f, V4_ERROR_NO_ONE); - CHECK(v4_fabric_remove(&f, far) == &pool[2], "node 12 is removed"); + CHECK(is_empty(said(12, "55 3 ROUTE")), "node 12 is told the way to 55 is by node 10, which has none"); + CHECK(strcmp(tell(12, ": C2 S\" 1 DROP\" 55 SEND BEGIN 0 UNTIL ; C2"), "(still running)") == 0 && pool[0].n.mem[OWED_COUNT] == 1 && !pool[0].n.asking, + "node 12 sends 55 a message and is then stuck in a loop: node 10 owes it a refusal, and is not blocked writing it"); step_cap = 20000000; - CHECK(strcmp(tell(10, "1 2 + ."), "3 ") == 0 && pool[0].n.mem[OWED_COUNT] == 0 && waiting(hera), "node 10 is let go, lets the refusal go, and goes on: \"%s\"", printed); + CHECK(strcmp(said(10, "1 2 + ."), "3 ") == 0 && pool[0].n.mem[OWED_COUNT] == 1, "node 10 goes on doing what it is sent, still owing: \"%s\"", printed); + { + v4_uheat_t clock; + unsigned k; + for (k = 0; k < 1000; k++) (void)v4_fabric_step(&f); + clock = pool[0].es.anticlock; + for (k = 0; k < 1000; k++) (void)v4_fabric_step(&f); + CHECK(v4_node_in_wait(&pool[0].n) && pool[0].es.anticlock == clock, "and sleeps in the wait between times"); + } + CHECK(v4_fabric_remove(&f, far) == &pool[2], "node 12 is removed"); + CHECK(strcmp(said(10, "1 2 + ."), "3 ") == 0 && pool[0].n.mem[OWED_COUNT] == 0 && waiting(hera) && !v4_node_in_wait(&pool[0].n), "node 10 lets the refusal go and is at rest: \"%s\"", printed); printf(" %d checks, %d failures\n", checks, failures); return failures != 0; diff --git a/v4/tests/test_host_quit.c b/v4/tests/test_host_quit.c index 2c6c7fb0..b9a5e1a2 100644 --- a/v4/tests/test_host_quit.c +++ b/v4/tests/test_host_quit.c @@ -213,6 +213,7 @@ static int run_line(long max) while (steps < max && idle < 64) { (void)v4_exec_step_word(&n, &es, &h); steps++; + (void)v4_node_offer_as_write(&n); /* in the wait: what it offers is a write, the kernel and the console taking at once */ if (n.asking && n.ask_port == 0) { kernel_serve(); v4_node_port_served(&n); continue; } /* a request */ if (n.asking && n.ask_port == CONSOLE_PORT) { /* a word of a message from the node */ v4_cell word = n.request; diff --git a/v4/tests/test_host_unit.c b/v4/tests/test_host_unit.c index 5167db89..f988783f 100644 --- a/v4/tests/test_host_unit.c +++ b/v4/tests/test_host_unit.c @@ -506,8 +506,8 @@ int main(void) /* a node is killed while its neighbour is writing to it */ step_limit = 3000000ul; CHECK(strcmp(tell(14, ": SPIN BEGIN 0 UNTIL ; SPIN"), "(still running)") == 0, "node 14 is stuck in a loop that never ends"); - CHECK(strcmp(tell(12, ": TO14 S\" 65 EMIT\" 14 SEND ; TO14"), "(still running)") == 0 && node_numbered(12)->asking, - "node 12, beside it, sends it text: 14 never reads, and 12 is blocked writing to it"); + CHECK(strcmp(tell(12, ": TO14 S\" 65 EMIT\" 14 SEND ; TO14"), "(still running)") == 0 && v4_node_in_wait(node_numbered(12)) && !node_numbered(12)->asking, + "node 12, beside it, sends it text: 14 never reads, and 12 waits to begin the message, in the wait"); { unsigned born = born_count; const char *r = tell(10, "14 KILL 65 EMIT"); @@ -551,8 +551,8 @@ int main(void) /* Hera blocked writing to a node that is stuck: a line from the console lets her go (MESH.md 7b.7) */ step_limit = 3000000ul; CHECK(strcmp(tell(11, ": SPIN BEGIN 0 UNTIL ; SPIN"), "(still running)") == 0, "node 11 is stuck in a loop"); - CHECK(strcmp(tell(10, ": T11 S\" 1 DROP\" 11 SEND 67 EMIT ; T11"), "(still running)") == 0 && node_numbered(10)->asking, - "Hera sends it text: its number is the higher, so she writes without looking, and is blocked"); + CHECK(strcmp(tell(10, ": T11 S\" 1 DROP\" 11 SEND 67 EMIT ; T11"), "(still running)") == 0 && v4_node_in_wait(node_numbered(10)) && !node_numbered(10)->asking, + "Hera sends it text: it never reads, and she waits to begin the message, in the wait"); { const char *r = tell(10, "11 KILL 68 EMIT"); CHECK(strstr(r, "Interrupted\n") != NULL && strstr(r, "D") != NULL && strstr(r, "C") == NULL && strstr(r, "Interrupted\n") < strstr(r, "D"),