Stage G: SEND, and two workers interleave; decision compares work heat (FABRIC-3.8 §3.8, §3.13.7)

SEND ( paddr plen name-c name-u -- ok? ): general kernel-Hermes send to a
named VM, from = calling VM, one block max (refused, not truncated), every
VM. New SK_HERMES_MSG_TYPE_SEND (30).

Ruling C-4 (beta), Captain Bob: the switch decision compares work heat --
the heat each VM pulled in by its own per-beat charges -- not absolute
heat, so Hera's structural endowment no longer makes her hottest. Before
it, the two-worker test ran serial (AAAA...BBBB); after it, byte-identical
on amd64/aarch64/riscv64:
AAABBBBBBBBAAAAAAAABBBBBAAAAABBBBBAAAAABBBBBAAAAABBBBBAAAAABBBBBAAAAABBBBBAAAABB
(40 A, 40 B, 16 runs; ordinary words only, nothing yields). Acceptance:
relay 3, idle growth 0; dict_hash set changed by the new word
(word_count 533) and identical across ISAs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-23 21:01:44 -04:00
co-authored by Claude Opus 5.5
parent c7185facf0
commit 81def7b4a5
18 changed files with 46044 additions and 7 deletions
+63
View File
@@ -489,10 +489,73 @@ static void sk_word_kh_elevate_send(VM *vm) {
vm_push(vm, rc == 0 ? 1 : 0);
}
/* FABRIC-3.8.md §3.8 (Stage G, 2026-09-23; name ruled by Captain Bob:
* "SEND"). SEND ( paddr plen name-c name-u -- ok? ): the general
* FORTH-callable kernel-Hermes send. Delivers a copy of the payload text
* to the VM named name-c/name-u, where it is interpreted -- on that VM's own
* native stack, by a switch, once the compudynamic decision chooses it.
* `from` is the calling VM, derived here, never taken from the stack (the
* anti-spoof rule KH-ELEVATE-SEND established). Bounded to one block of
* text (the payload is sent NUL-terminated, so at most
* SK_HERMES_CHUNK_MAX_PAYLOAD - 1 characters); an oversized payload is
* refused, not truncated -- truncated code would run as different code.
* A plain, unconditional primitive: restricting who may SEND is ACL.4th's
* job, never a C check. Returns 1 if admitted, 0 if refused (no such VM,
* dead, oversized, bad address, or kernel-Hermes refused: queue full or the
* sender's reservoir can't fund it). */
static char g_send_buf[SK_HERMES_CHUNK_MAX_PAYLOAD];
static void sk_word_send(VM *vm) {
cell_t name_u, name_c, plen, paddr;
char name[VM_NAME_MAX];
VMRegistryEntry target;
const char *src;
int i, rc;
if (vm->dsp < 3) {
console_println("SEND: expects paddr plen S\" name\" SEND");
vm->error = 1;
return;
}
name_u = vm_pop(vm);
name_c = vm_pop(vm);
plen = vm_pop(vm);
paddr = vm_pop(vm);
if (name_u <= 0 || (uint32_t)name_u >= VM_NAME_MAX ||
plen < 0 || plen > SK_HERMES_CHUNK_MAX_PAYLOAD - 1) {
vm_push(vm, 0);
return;
}
src = (const char *)vm_ptr(vm, (vaddr_t)name_c);
if (!src) { vm_push(vm, 0); return; }
for (i = 0; i < (int)name_u; i++) name[i] = src[i];
name[name_u] = '\0';
if (capsule_vm_find_by_name_nocase(name, &target) != 0 || !target.vm_ptr ||
target.state == VM_STATE_DEAD || target.state == VM_STATE_STILLBORN) {
vm_push(vm, 0);
return;
}
if (plen > 0) {
src = (const char *)vm_ptr(vm, (vaddr_t)paddr);
if (!src) { vm_push(vm, 0); return; }
for (i = 0; i < (int)plen; i++) g_send_buf[i] = src[i];
}
g_send_buf[plen] = '\0';
rc = sk_hermes_send_one(vm->stadium_vm_id, target.vm_id,
SK_HERMES_MSG_TYPE_SEND, 0,
g_send_buf, (uint32_t)(plen + 1));
vm_push(vm, rc == 0 ? 1 : 0);
}
void sk_repl_register_words(VM *vm) {
register_word(vm, "BLK-ATTACH-ACK", sk_word_blk_attach_ack);
register_word(vm, "KH-BLK-ATTACH-SEND", sk_word_kh_blk_attach_send);
register_word(vm, "KH-ELEVATE-SEND", sk_word_kh_elevate_send);
register_word(vm, "SEND", sk_word_send); /* FABRIC-3.8.md §3.8 */
}
/*===========================================================================