fix(v4.0.0): step 6e review round 1 -- a take that does not take does nothing; output and answers wait at a middle node; no queue on the kernel's port; a printing wait is not interrupted
- The result of every take is looked at: a wire cut between the look and the take leaves nothing acted on (the text before run again, a refusal counted, a wait ended by an old answer, a way forgotten). - A node with no room to pass on what another printed, or its word of how text ended, leaves it on the wire it came by and moves it when there is room; what is behind it for the same port waits too. Sleep for room (9) is woken by room on any of the node's wires (engine; MESH.md 7d.3). - The lone node's host keeps no queue for the kernel's port: a message to it is error 18. The step limit is counted while the node waits for room. - A text waiting for room to print is not interrupted by console text; AWAIT is, as before. (BREAK?) is gone. - A GONE is believed only by the centre's port; unawaited answers let go are counted; nothing past a message's last character goes on a wire; AWAIT sets (AWAIT-FROM) only once the stack has been tried. - test_host_depth.c: ten paths, each run works or ends in one named stack error; it fails with (ROOM) or (ROOM-SERVE) taken out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b1d09af043
commit
6a7d0aa27f
+30
-28
@@ -93,15 +93,18 @@ static uint32_t word_count(const v4_node *n, const v4_image *im)
|
||||
/* What the kernel keeps of the node's block window (blocks.h). */
|
||||
static v4_blocks boot_blocks;
|
||||
|
||||
/* THE WIRES (docs/v4.0.0/MESH.md 7d.5). The lone node has no fabric: the
|
||||
* boot keeps the queues of its two wires, a queue each way (wire.h), and
|
||||
* does what the node asks of them, as a fabric does for a node of a mesh
|
||||
* (fabric.c). Every other port has no one on it. The kernel's wire has
|
||||
* its queues as any wire has; the kernel puts nothing on it and takes
|
||||
* nothing off: its requests are words, not messages. */
|
||||
static v4_wire_queue boot_wire[2][2]; /* by port: [0] to the node, [1] from it */
|
||||
#define TO_NODE(port) (&boot_wire[port][0])
|
||||
#define FROM_NODE(port) (&boot_wire[port][1])
|
||||
/* THE WIRE (docs/v4.0.0/MESH.md 7d.5). The lone node has no fabric: the
|
||||
* boot keeps the two queues of its console's wire, one each way (wire.h),
|
||||
* and does what the node asks of them, as a fabric does for a node of a
|
||||
* mesh (fabric.c).
|
||||
* THE KERNEL'S PORT HAS NO QUEUE (ruled 2026-10-08). The kernel is asked by
|
||||
* words written to port 0 and takes no messages: a message for that port
|
||||
* -- SEND-ON to it, or what a text prints when the way to its console has
|
||||
* been set there -- is refused at once, as on any port with no one to take
|
||||
* messages: the node's error 18, "No one on that port". */
|
||||
static v4_wire_queue boot_wire[2]; /* the console's: [0] to the node, [1] from it */
|
||||
#define TO_NODE (&boot_wire[0])
|
||||
#define FROM_NODE (&boot_wire[1])
|
||||
|
||||
/* 1 if `count` words from `addr` are the node's memory and not its ports
|
||||
* or the addresses after them: they may be copied to and from. */
|
||||
@@ -113,20 +116,17 @@ static int span_ok(const v4_node *n, v4_cell addr, unsigned count)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int boot_arrived(void)
|
||||
{
|
||||
return TO_NODE(KERNEL_PORT)->arrived || TO_NODE(CONSOLE_PORT)->arrived;
|
||||
}
|
||||
|
||||
/* The node is blocked at an operation on a wire (node.h, v4_node_doing):
|
||||
* do it, whole, and let the node go on; the operations and their answers
|
||||
* are MESH.md 7d.3's, as fabric.c does them. Returns 0 if the node sleeps
|
||||
* on: it asked to sleep (8), and no message has come since it last asked
|
||||
* which wires have one; or for room (9) that is not there. */
|
||||
* which wires have one; or for room (9) that is not there, and nothing
|
||||
* has come off its wire either. */
|
||||
static int boot_do(const v4_boot *bt)
|
||||
{
|
||||
v4_node *n = bt->n;
|
||||
v4_wire_queue *rx = n->wire <= CONSOLE_PORT ? TO_NODE(n->wire) : 0, *tx = n->wire <= CONSOLE_PORT ? FROM_NODE(n->wire) : 0;
|
||||
v4_wire_queue *rx = n->wire == CONSOLE_PORT ? TO_NODE : 0, *tx = n->wire == CONSOLE_PORT ? FROM_NODE : 0;
|
||||
v4_cell a = n->wire_a, b = n->wire_b, h[V4_WIRE_HEADER], how = V4_WIRE_NO_ONE;
|
||||
unsigned cells;
|
||||
|
||||
@@ -146,7 +146,7 @@ static int boot_do(const v4_boot *bt)
|
||||
case 3: /* move */
|
||||
if (!rx) break;
|
||||
if (rx->mark >= rx->used) how = V4_WIRE_NO_MESSAGE;
|
||||
else how = a >= 0 && a <= (v4_cell)CONSOLE_PORT ? v4_wire_move(rx, FROM_NODE((unsigned)a)) : V4_WIRE_NO_ONE;
|
||||
else how = a == (v4_cell)CONSOLE_PORT ? v4_wire_move(rx, FROM_NODE) : V4_WIRE_NO_ONE;
|
||||
break;
|
||||
case 4: /* drop */
|
||||
if (rx) how = v4_wire_drop(rx);
|
||||
@@ -164,14 +164,15 @@ static int boot_do(const v4_boot *bt)
|
||||
if (rx) how = v4_wire_next(rx);
|
||||
break;
|
||||
case 8: /* sleep */
|
||||
if (!boot_arrived()) return 0;
|
||||
if (!TO_NODE->arrived) return 0;
|
||||
how = V4_WIRE_DONE;
|
||||
break;
|
||||
case 9: /* sleep for room */
|
||||
if (!tx) break;
|
||||
if (a < 0 || a > (v4_cell)V4_WIRE_CELLS) { how = V4_WIRE_NO_ROOM; break; }
|
||||
if (v4_wire_room(tx, (unsigned)a) == V4_WIRE_DONE) { how = V4_WIRE_DONE; break; }
|
||||
if (!boot_arrived()) return 0;
|
||||
if (!TO_NODE->arrived && !FROM_NODE->freed) return 0; /* a message has come, or the console has taken one */
|
||||
FROM_NODE->freed = 0;
|
||||
how = V4_WIRE_NO_ROOM;
|
||||
break;
|
||||
case 10: /* room */
|
||||
@@ -192,11 +193,10 @@ static int boot_do(const v4_boot *bt)
|
||||
static void boot_exec(const v4_boot *b)
|
||||
{
|
||||
v4_node *n = b->n;
|
||||
v4_node_have(n, (TO_NODE(KERNEL_PORT)->used ? 1u << KERNEL_PORT : 0u) | (TO_NODE(CONSOLE_PORT)->used ? 1u << CONSOLE_PORT : 0u));
|
||||
v4_node_have(n, TO_NODE->used ? 1u << CONSOLE_PORT : 0u);
|
||||
(void)v4_exec_step_word(n, b->es, b->h);
|
||||
if (n->have_fetched) {
|
||||
TO_NODE(KERNEL_PORT)->arrived = 0;
|
||||
TO_NODE(CONSOLE_PORT)->arrived = 0;
|
||||
TO_NODE->arrived = 0;
|
||||
n->have_fetched = 0;
|
||||
}
|
||||
}
|
||||
@@ -225,14 +225,14 @@ static int run_line(const v4_boot *b, const char *text, unsigned len, char *keep
|
||||
|
||||
if (text) { /* with none, the node has a line waiting on its wire (boot.h) */
|
||||
if (!v4_message_text(&out, 0, CONSOLE_ID, V4_MSG_TEXT, text, len)) return V4_BOOT_LINE_TOO_LONG;
|
||||
if (v4_wire_put(TO_NODE(CONSOLE_PORT), out.word, out.word + V4_MSG_HEADER) != V4_WIRE_DONE) return V4_BOOT_LINE_STOPPED;
|
||||
if (v4_wire_put(TO_NODE, out.word, out.word + V4_MSG_HEADER) != V4_WIRE_DONE) return V4_BOOT_LINE_STOPPED;
|
||||
}
|
||||
for (;;) {
|
||||
int awake = boot_step(b);
|
||||
if (n->stopped) return V4_BOOT_LINE_STOPPED;
|
||||
|
||||
v4_wire_first(FROM_NODE(CONSOLE_PORT)); /* what the node has sent its console, in the order it was sent */
|
||||
while (v4_wire_take(FROM_NODE(CONSOLE_PORT), in, in_text, V4_MSG_MAX_CHARS / 4u) == V4_WIRE_DONE) {
|
||||
v4_wire_first(FROM_NODE); /* what the node has sent its console, in the order it was sent */
|
||||
while (v4_wire_take(FROM_NODE, in, in_text, V4_MSG_MAX_CHARS / 4u) == V4_WIRE_DONE) {
|
||||
if (in[2] == V4_MSG_OUTPUT) {
|
||||
for (i = 0; i < (unsigned)in[6]; i++) {
|
||||
char c = (char)(((v4_ucell)in_text[i / 4u] >> (8u * (i % 4u))) & 0xFFu);
|
||||
@@ -248,7 +248,10 @@ static int run_line(const v4_boot *b, const char *text, unsigned len, char *keep
|
||||
}
|
||||
}
|
||||
if (!awake) {
|
||||
if (n->do_op == 9) continue; /* waiting for room, which the console has just made */
|
||||
if (n->do_op == 9) { /* waiting for room, which the console has just made */
|
||||
if (++steps > STEP_LIMIT) return V4_BOOT_LINE_STOPPED;
|
||||
continue;
|
||||
}
|
||||
return V4_BOOT_LINE_WAITING; /* waiting for an answer: only the console can end that */
|
||||
}
|
||||
|
||||
@@ -474,9 +477,8 @@ int v4_boot_run(const v4_boot *b)
|
||||
say(b, "V4: the nucleus is not for this build of the engine\nPARITY:FAIL\nPOST: FAILED\n");
|
||||
return 0;
|
||||
}
|
||||
/* its two wires, the kernel's and the console's, with nothing on them */
|
||||
v4_wire_reset(TO_NODE(KERNEL_PORT)); v4_wire_reset(FROM_NODE(KERNEL_PORT));
|
||||
v4_wire_reset(TO_NODE(CONSOLE_PORT)); v4_wire_reset(FROM_NODE(CONSOLE_PORT));
|
||||
/* its console's wire, with nothing on it */
|
||||
v4_wire_reset(TO_NODE); v4_wire_reset(FROM_NODE);
|
||||
v4_blocks_init(&boot_blocks, b->im->block_window);
|
||||
if (!load_nucleus(b)) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user