revert(v4.0.0): step 6d, the wait, is backed out -- two reviews found it unsound
Ruled 2026-10-08. The engine, the nucleus and their tests are as they
were at dfabfa46, before step 6d; the code of the wait and its tests are
in history at 075385ab..2cf37aab. The limit of MESH.md 7b.7 stands: a
node that is stuck can hold up its neighbours until Hera kills it.
MESH.md 7c is kept as the record of the design as approved, and 7c.6 says
what was built, what the two reviews found, the cause the findings share
-- a node's message machinery runs on the stacks its text is using, and a
fault abandons whatever was in progress -- and what a second attempt
must settle before anything is built.
Kept from it, in hosted-check: a line that leaves 29 values on the stack,
and WORDS with 26 values on it. Both hung the products at some commit of
the wait.
make -C v4 test and sanitize at both widths, hosted-check, lint; three
bare-metal boots typing both. POST 538 of 538, word_count=317,
dict_hash=0xc0769523a47b7dc3 on all six: the hash of step 6c's code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
10f5ffd00b
commit
6015c87157
+14
-70
@@ -93,14 +93,7 @@ void v4_node_store(v4_node *n, v4_cell addr, v4_cell value)
|
||||
n->asking = 1;
|
||||
return;
|
||||
}
|
||||
if (port >= (int)V4_PORT_OFFER && port < (int)V4_PORT_WAIT) { /* an offer: remembered until the wait */
|
||||
unsigned k = (unsigned)port - V4_PORT_OFFER;
|
||||
n->offer[k] = value;
|
||||
n->offers |= 1u << k;
|
||||
return;
|
||||
}
|
||||
if (port == (int)V4_PORT_WAIT) { n->offers = 0; return; } /* a store to the wait: every offer is withdrawn */
|
||||
if (port >= 0) { v4_node_fault(n, V4_FAULT_ADDRESS, addr); return; } /* "any", "which port" and the rest are not written to */
|
||||
if (port >= 0) { v4_node_fault(n, V4_FAULT_ADDRESS, addr); return; } /* "any" and "which port" are not written to */
|
||||
}
|
||||
/* The stack registers: a store empties the stack. -1 when not attached. */
|
||||
if (addr == n->dstack_reg) { v4_dstack_clear(&n->ds); return; }
|
||||
@@ -127,16 +120,8 @@ v4_cell v4_node_fetch(v4_node *n, v4_cell addr)
|
||||
{
|
||||
int port = v4_node_port_index(n, addr);
|
||||
if (port == (int)V4_PORTS + 1) return (v4_cell)n->last_from;
|
||||
if (port == (int)V4_PORTS + 2) return (v4_cell)n->writers;
|
||||
if (port == (int)V4_PORTS + 3) return (v4_cell)n->readers;
|
||||
if (port == (int)V4_PORT_WAIT || port == (int)V4_PORT_WAIT1) {
|
||||
/* the wait: the word that came, or 0 for an offer taken */
|
||||
if (!n->given) return 0;
|
||||
n->given = 0;
|
||||
n->last_from = n->given_port;
|
||||
return n->given_value;
|
||||
}
|
||||
if (port >= (int)V4_PORT_OFFER) return 0; /* an offer is not read back */
|
||||
if (port == (int)V4_PORTS + 2) { n->since_look = 0; return (v4_cell)n->writers; }
|
||||
if (port == (int)V4_PORTS + 3) { n->since_look = 0; return (v4_cell)n->readers; }
|
||||
if (port >= 0) {
|
||||
/* the word its neighbour wrote; v4_node_read_ready has said it is there */
|
||||
if (!n->given) return 0;
|
||||
@@ -194,9 +179,7 @@ void v4_node_port_attach(v4_node *n, v4_cell base)
|
||||
n->last_from = 0;
|
||||
n->writers = 0;
|
||||
n->readers = 0;
|
||||
n->offers = 0;
|
||||
n->waiting = 0;
|
||||
n->offer_asked = 0;
|
||||
n->since_look = 0;
|
||||
}
|
||||
|
||||
void v4_node_port_status(v4_node *n, unsigned writers, unsigned readers)
|
||||
@@ -207,19 +190,17 @@ void v4_node_port_status(v4_node *n, unsigned writers, unsigned readers)
|
||||
|
||||
int v4_node_port_index(const v4_node *n, v4_cell addr)
|
||||
{
|
||||
if (n->port < 0 || addr < n->port || addr > n->port + (v4_cell)V4_PORT_WAIT1) return -1;
|
||||
if (n->port < 0 || addr < n->port || addr > n->port + (v4_cell)V4_PORTS + 3) return -1;
|
||||
return (int)(addr - n->port);
|
||||
}
|
||||
|
||||
int v4_node_read_ready(v4_node *n, v4_cell addr)
|
||||
{
|
||||
int port = v4_node_port_index(n, addr);
|
||||
if (port < 0 || (port > (int)V4_PORT_ANY && port != (int)V4_PORT_WAIT && port != (int)V4_PORT_WAIT1)) return 1;
|
||||
if (n->given && (port >= (int)V4_PORT_ANY || (unsigned)port == n->given_port)) return 1;
|
||||
if (port < 0 || port > (int)V4_PORT_ANY) return 1;
|
||||
if (n->given && (port == (int)V4_PORT_ANY || (unsigned)port == n->given_port)) return 1;
|
||||
n->reading = 1;
|
||||
n->waiting = port >= (int)V4_PORT_WAIT; /* the wait is a read of any port, with offers standing; */
|
||||
n->read_port = port == (int)V4_PORT_WAIT ? V4_PORT_ANY /* the wait for an offer only reads no port at all */
|
||||
: (unsigned)port;
|
||||
n->read_port = (unsigned)port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,39 +210,6 @@ void v4_node_port_give(v4_node *n, unsigned port, v4_cell value)
|
||||
n->given_value = value;
|
||||
n->given_port = port;
|
||||
n->reading = 0;
|
||||
if (n->waiting) { n->waiting = 0; n->offers = 0; } /* the wait is over: every offer is withdrawn */
|
||||
}
|
||||
|
||||
int v4_node_in_wait(const v4_node *n)
|
||||
{
|
||||
return n->waiting && n->reading && !n->given;
|
||||
}
|
||||
|
||||
int v4_node_offer_taken(v4_node *n, unsigned k)
|
||||
{
|
||||
if (!v4_node_in_wait(n) || k >= V4_PORTS || !(n->offers & (1u << k))) return 0;
|
||||
v4_node_port_give(n, V4_PORTS + k, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int v4_node_offer_gone(v4_node *n, unsigned k)
|
||||
{
|
||||
if (n->error_reg < 0 || n->fault_vector < 0 || n->stopped) return 0;
|
||||
if (!v4_node_in_wait(n) || k >= V4_PORTS || !(n->offers & (1u << k))) return 0;
|
||||
v4_node_port_give(n, 2u * V4_PORTS + k, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int v4_node_offer_as_write(v4_node *n)
|
||||
{
|
||||
unsigned k;
|
||||
if (!v4_node_in_wait(n) || n->offers == 0 || n->asking) return 0;
|
||||
for (k = 0; !(n->offers & (1u << k)); k++) { }
|
||||
n->request = n->offer[k];
|
||||
n->ask_port = k;
|
||||
n->asking = 1;
|
||||
n->offer_asked = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void v4_node_born(v4_node *n, v4_cell base)
|
||||
@@ -274,23 +222,19 @@ void v4_node_born(v4_node *n, v4_cell base)
|
||||
void v4_node_port_served(v4_node *n)
|
||||
{
|
||||
n->asking = 0;
|
||||
if (n->offer_asked) { /* what was served was an offer: the wait is over */
|
||||
n->offer_asked = 0;
|
||||
v4_node_port_give(n, V4_PORTS + n->ask_port, 0);
|
||||
}
|
||||
n->since_look++;
|
||||
}
|
||||
|
||||
unsigned v4_node_words_since_look(const v4_node *n)
|
||||
{
|
||||
return n->since_look;
|
||||
}
|
||||
|
||||
int v4_node_port_gone(v4_node *n, v4_cell code)
|
||||
{
|
||||
if (code == 0 || n->error_reg < 0 || n->fault_vector < 0 || n->stopped) return 0;
|
||||
if (n->asking && n->offer_asked) { /* what it wrote was an offer: it is told, not faulted */
|
||||
n->asking = 0; n->offer_asked = 0;
|
||||
v4_node_port_give(n, 2u * V4_PORTS + n->ask_port, 0);
|
||||
return 1;
|
||||
}
|
||||
if (n->asking) n->asking = 0;
|
||||
else if (n->reading && !n->given && n->read_port < V4_PORTS) n->reading = 0;
|
||||
else if (n->reading && !n->given && n->read_port != V4_PORT_ANY) n->reading = 0;
|
||||
else return 0;
|
||||
v4_node_store(n, n->error_reg, code); /* raises it: P is the node's handler now */
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user