Console sessions now route through the same general VM-to-VM messaging system (Phase C) any VM can already use for its own reasons -- not a synchronous shortcut. Per direct instruction: real async MSG-SEND/ MSG-DELIVER (Option B), not a VM-EXEC-based synchronous relay, because messaging is a general capability, not a console-specific mechanism. New CONSOLE-CMD-EVENT message type (common:messaging.4th). New sk_repl_dispatch_line() (repl.c), called from both sk_repl_step and sk_repl_run in place of a direct vm_interpret(): if the active VM's own name has a live "<name>~user" counterpart registered, the raw input line is wrapped as an S"-embedded CONSOLE-CMD-EVENT MSG-SEND and interpreted on the console VM instead of being run directly -- the console's own next MSG-TICK (Hera's idle pump) delivers it into the paired user VM via VM-EXEC, same mechanism every other message already uses. Falls back to direct interpretation if there's no pairing, or if the line contains a `"` (known v1 limitation, warned about explicitly rather than silently mishandled). New capsule_console_birth() (capsule_console.h/.c): a bare VM whose only content is loading common:messaging.4th -- the console side of a pairing, parallel in shape to RUNCAP's user-VM birth but with fixed embedded content instead of a devblock read (no identity, no thumbdrive involved). New PAIR-TEST diagnostic word (mama_forth_words.c, matches RUNCAP-TEST's own precedent): births both halves of a pairing and registers the "<name>~user" mapping. Not the real pairing call site -- that's the eventual attach/onboarding flow -- this exists to exercise the relay live before that flow exists. Found and fixed a real, serious bug live: console_set_vm_name() stored the caller's raw pointer instead of copying it. mama_word_use() (USE) passes a VMRegistryEntry field living on its own stack frame -- once USE returns, that pointer dangles, corrupting every console tag after the first USE (observed directly as garbled "[[]" / binary-looking prefixes instead of "[CaptBob]"). Fixed at the source: console_set_ vm_name() now copies into internal storage. That surfaced a second, related bug across every console_get_vm_name()-based save/restore call site in mama_forth_words.c (BIRTH, VM-STEP, VM-EXEC, CONNECT-HERMES, CONNECT-ARTEMIS): saving just a pointer into the single internal buffer meant an intervening console_set_vm_name() call silently corrupted the saved value before the restore ever ran. New console_save_vm_name() copies into caller-owned storage; every save/restore site updated. Verified end-to-end, live in QEMU: typed WELCOME at a paired console VM -- it did not execute directly (no UNKNOWN WORD), printed ok immediately (queued, async), and on the next idle tick "[CaptBob~user] Minted identity -- default personality" appeared on its own -- genuine delivery and execution in the paired user VM through the real MSG-SEND/MSG-DELIVER pipeline. Console tags confirmed clean (no garbling) across all three architectures' full regression boot. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
438 lines
13 KiB
Forth
438 lines
13 KiB
Forth
Block 5003
|
|
( common:messaging.4th -- generic per-VM messaging vocab. )
|
|
1 CONSTANT SPAWN-EVENT
|
|
2 CONSTANT PAUSE-EVENT
|
|
3 CONSTANT RESUME-EVENT
|
|
4 CONSTANT KILL-EVENT
|
|
0 CONSTANT CH-NEGOTIATING
|
|
1 CONSTANT CH-OPEN
|
|
2 CONSTANT CH-CLOSING
|
|
9 CONSTANT MSG-CELLS
|
|
6 CONSTANT CH-CELLS
|
|
2 CONSTANT MBR-CELLS
|
|
32 CONSTANT MSG-MAX
|
|
16 CONSTANT CH-MAX
|
|
64 CONSTANT MBR-MAX
|
|
65208 CONSTANT Q-DECAY
|
|
255 CONSTANT MSG-DELIVERED
|
|
Block 5038
|
|
( CONSOLE-CMD-EVENT: console-VM -> paired user-VM command )
|
|
( relay message type, async MSG-SEND/MSG-DELIVER. )
|
|
7 CONSTANT CONSOLE-CMD-EVENT
|
|
Block 5004
|
|
( StadiumBehaviour tags, match stadium.h's enum )
|
|
0 CONSTANT SB-MIGRATE
|
|
1 CONSTANT SB-DELIVER
|
|
2 CONSTANT SB-EXPIRE
|
|
3 CONSTANT SB-COOL
|
|
-1 CONSTANT STADIUM-NONE
|
|
( per-item admission heat for MSG-SEND/CH-ACCEPT. )
|
|
( Remaining reservoir after COMMON-CH's Q.1/3 floor, split )
|
|
( evenly across MSG-MAX messages + non-COMMON CH-MAX-1 slots. )
|
|
Q.1 Q.1 3 / - MSG-MAX CH-MAX 1- + / CONSTANT Q.SLOT
|
|
Block 5005
|
|
( arenas. heat/capacity via Stadium; MBR keeps its own )
|
|
( free list (not part of heat economy). )
|
|
CREATE MSG-ARENA MSG-MAX MSG-CELLS * CELLS ALLOT
|
|
CREATE CH-ARENA CH-MAX CH-CELLS * CELLS ALLOT
|
|
CREATE MBR-ARENA MBR-MAX MBR-CELLS * CELLS ALLOT
|
|
VARIABLE MSG-ALLOC-SLOT
|
|
VARIABLE CH-ALLOC-SLOT
|
|
VARIABLE MBR-FREE-HEAD
|
|
VARIABLE MSG-SEQ
|
|
VARIABLE CH-ACTIVE
|
|
VARIABLE COMMON-CH
|
|
Block 5006
|
|
( VM name routing table -- same fixed table every VM loads, )
|
|
( so IDX>NAME resolves identically everywhere. )
|
|
8 CONSTANT VM-MAX
|
|
CREATE VM-NAME-ADDRS VM-MAX CELLS ALLOT
|
|
CREATE VM-NAME-LENS VM-MAX CELLS ALLOT
|
|
: VM-NAME-REG ( addr u idx -- )
|
|
DUP VM-MAX >= IF DROP 2DROP EXIT THEN
|
|
>R R@ CELLS VM-NAME-LENS + !
|
|
R> CELLS VM-NAME-ADDRS + ! ;
|
|
: VM-NAMES-INIT ( -- )
|
|
S" Hera" 0 VM-NAME-REG
|
|
S" Hermes" 1 VM-NAME-REG
|
|
S" Artemis" 2 VM-NAME-REG ;
|
|
Block 5007
|
|
( INIT-FREE. stamps STADIUM-NONE into each slot's stadium- )
|
|
( cell field (msg off 5, ch off 3). Raw offsets: accessors )
|
|
( aren't defined yet in file order. )
|
|
: MSG-INIT-FREE ( -- )
|
|
MSG-MAX 0 DO
|
|
STADIUM-NONE I MSG-CELLS * CELLS MSG-ARENA + 5 CELLS + !
|
|
LOOP ;
|
|
: CH-INIT-FREE ( -- )
|
|
CH-MAX 0 DO
|
|
STADIUM-NONE I CH-CELLS * CELLS CH-ARENA + 3 CELLS + !
|
|
LOOP ;
|
|
Block 5008
|
|
( MBR-INIT-FREE (member free list, untouched) )
|
|
: MBR-INIT-FREE ( -- )
|
|
MBR-MAX 1- 0 DO
|
|
I MBR-CELLS * CELLS MBR-ARENA +
|
|
I 1+ MBR-CELLS * CELLS MBR-ARENA + SWAP !
|
|
LOOP
|
|
0 MBR-MAX 1- MBR-CELLS * CELLS MBR-ARENA + !
|
|
MBR-ARENA MBR-FREE-HEAD ! ;
|
|
Block 5009
|
|
( MSG-ALLOC: finds a free slot (TYPE=0) first, admits into )
|
|
( Stadium only once confirmed free (no leak). )
|
|
: MSG-FIND-FREE-SLOT ( -- addr|0 )
|
|
MSG-ARENA MSG-MAX 0 DO
|
|
DUP @ 0= IF UNLOOP EXIT THEN
|
|
MSG-CELLS CELLS +
|
|
LOOP DROP 0 ;
|
|
Block 5010
|
|
( MSG-ALLOC: pulls heat from reservoir first, admits )
|
|
( (identity=idx, heat=pulled), rolls back on refusal. )
|
|
: MSG-ALLOC ( heat -- addr|0 )
|
|
MSG-FIND-FREE-SLOT DUP 0= IF SWAP DROP EXIT THEN
|
|
MSG-ALLOC-SLOT !
|
|
STADIUM-RES-PULL
|
|
MSG-ALLOC-SLOT @ MSG-ARENA - MSG-CELLS CELLS /
|
|
SWAP DUP >R
|
|
SB-DELIVER STADIUM-ADMIT
|
|
DUP STADIUM-NONE = IF
|
|
DROP R> STADIUM-RES-PUSH 0 EXIT
|
|
THEN
|
|
R> DROP
|
|
MSG-ALLOC-SLOT @ MSG-CELLS CELLS 0 FILL
|
|
MSG-ALLOC-SLOT @ 5 CELLS + !
|
|
MSG-ALLOC-SLOT @ ;
|
|
Block 5011
|
|
( MSG-FREE-NODE: evict from Stadium, clear field )
|
|
: MSG-FREE-NODE ( addr -- )
|
|
DUP 5 CELLS + @ STADIUM-EVICT DROP
|
|
DUP 5 CELLS + STADIUM-NONE SWAP !
|
|
DROP ;
|
|
Block 5012
|
|
( MBR alloc/free (unchanged; not heat economy) )
|
|
: MBR-ALLOC ( -- addr|0 )
|
|
MBR-FREE-HEAD @ DUP 0= IF EXIT THEN
|
|
DUP @ MBR-FREE-HEAD !
|
|
DUP MBR-CELLS CELLS 0 FILL ;
|
|
: MBR-FREE-NODE ( addr -- )
|
|
MBR-FREE-HEAD @ OVER ! MBR-FREE-HEAD ! ;
|
|
Block 5013
|
|
( CH-FIND-FREE-SLOT. No TYPE field, so freeness is )
|
|
( stadium-cell = STADIUM-NONE. CH-ALLOC -> block 4176. )
|
|
: CH-FIND-FREE-SLOT ( -- addr|0 )
|
|
CH-ARENA CH-MAX 0 DO
|
|
DUP 3 CELLS + @ STADIUM-NONE = IF UNLOOP EXIT THEN
|
|
CH-CELLS CELLS +
|
|
LOOP DROP 0 ;
|
|
Block 5014
|
|
( CH-ALLOC: pulls heat from reservoir first, admits )
|
|
( (identity=idx, heat=pulled), rolls back on refusal. )
|
|
: CH-ALLOC ( heat -- addr|0 )
|
|
CH-FIND-FREE-SLOT DUP 0= IF SWAP DROP EXIT THEN
|
|
CH-ALLOC-SLOT !
|
|
STADIUM-RES-PULL
|
|
CH-ALLOC-SLOT @ CH-ARENA - CH-CELLS CELLS /
|
|
SWAP DUP >R
|
|
SB-COOL STADIUM-ADMIT
|
|
DUP STADIUM-NONE = IF
|
|
DROP R> STADIUM-RES-PUSH 0 EXIT
|
|
THEN
|
|
R> DROP
|
|
CH-ALLOC-SLOT @ CH-CELLS CELLS 0 FILL
|
|
CH-ALLOC-SLOT @ 3 CELLS + !
|
|
CH-ALLOC-SLOT @ ;
|
|
Block 5015
|
|
( CH-FREE-NODE: evict from Stadium, clear field )
|
|
: CH-FREE-NODE ( addr -- )
|
|
DUP 3 CELLS + @ STADIUM-EVICT DROP
|
|
DUP 3 CELLS + STADIUM-NONE SWAP !
|
|
DROP ;
|
|
Block 5016
|
|
( message field accessors )
|
|
: MSG-TYPE@ ( m -- n ) @ ;
|
|
: MSG-TYPE! ( n m -- ) ! ;
|
|
: MSG-FROM@ ( m -- n ) 1 CELLS + @ ;
|
|
: MSG-FROM! ( n m -- ) 1 CELLS + ! ;
|
|
: MSG-TO@ ( m -- n ) 2 CELLS + @ ;
|
|
: MSG-TO! ( n m -- ) 2 CELLS + ! ;
|
|
: MSG-PADDR@ ( m -- a ) 3 CELLS + @ ;
|
|
: MSG-PADDR! ( a m -- ) 3 CELLS + ! ;
|
|
: MSG-PLEN@ ( m -- u ) 4 CELLS + @ ;
|
|
: MSG-PLEN! ( u m -- ) 4 CELLS + ! ;
|
|
( offset 5 = Stadium cell idx. MSG-HEAT@/! -> 4154. )
|
|
: MSG-STADIUM-CELL@ ( m -- cell ) 5 CELLS + @ ;
|
|
: MSG-STADIUM-CELL! ( cell m -- ) 5 CELLS + ! ;
|
|
: MSG-SEQ@ ( m -- n ) 6 CELLS + @ ;
|
|
: MSG-SEQ! ( n m -- ) 6 CELLS + ! ;
|
|
Block 5017
|
|
( message accessors: CH@/CH! )
|
|
: MSG-CH@ ( m -- c ) 7 CELLS + @ ;
|
|
: MSG-CH! ( c m -- ) 7 CELLS + ! ;
|
|
: MSG-ORIG-TYPE@ ( m -- n ) 8 CELLS + @ ;
|
|
: MSG-ORIG-TYPE! ( n m -- ) 8 CELLS + ! ;
|
|
253 CONSTANT MSG-NACKED
|
|
Block 5018
|
|
( channel + member accessors )
|
|
: CH-ID@ ( c -- n ) @ ;
|
|
: CH-ID! ( n c -- ) ! ;
|
|
: CH-OWNER@ ( c -- n ) 1 CELLS + @ ;
|
|
: CH-OWNER! ( n c -- ) 1 CELLS + ! ;
|
|
: CH-STATE@ ( c -- n ) 2 CELLS + @ ;
|
|
: CH-STATE! ( n c -- ) 2 CELLS + ! ;
|
|
( offset 3 = Stadium cell index. CH-HEAT@/! -> 4154. )
|
|
: CH-STADIUM-CELL@ ( c -- cell ) 3 CELLS + @ ;
|
|
: CH-STADIUM-CELL! ( cell c -- ) 3 CELLS + ! ;
|
|
: CH-MBRS@ ( c -- a ) 4 CELLS + @ ;
|
|
: CH-MBRS! ( a c -- ) 4 CELLS + ! ;
|
|
: CH-NEXT@ ( c -- a ) 5 CELLS + @ ;
|
|
: CH-NEXT! ( a c -- ) 5 CELLS + ! ;
|
|
: MBR-NEXT@ ( m -- a ) @ ;
|
|
: MBR-VM@ ( m -- n ) 1 CELLS + @ ;
|
|
Block 5019
|
|
( composed MSG/CH-HEAT@/!, same names/stacks, bodies )
|
|
( routed via Stadium. Callers need no changes. )
|
|
: MSG-HEAT@ ( m -- q ) MSG-STADIUM-CELL@ STADIUM-HEAT@ ;
|
|
: MSG-HEAT! ( q m -- ) MSG-STADIUM-CELL@ STADIUM-HEAT! ;
|
|
: CH-HEAT@ ( c -- q ) CH-STADIUM-CELL@ STADIUM-HEAT@ ;
|
|
: CH-HEAT! ( q c -- ) CH-STADIUM-CELL@ STADIUM-HEAT! ;
|
|
Block 5020
|
|
( deliver )
|
|
VARIABLE MSG-LAST-MSG
|
|
: IDX>NAME ( idx -- addr u )
|
|
DUP VM-MAX >= IF DROP 0 0 EXIT THEN
|
|
DUP CELLS VM-NAME-ADDRS + @
|
|
SWAP CELLS VM-NAME-LENS + @ ;
|
|
: MSG-DELIVER ( m -- )
|
|
DUP MSG-LAST-MSG !
|
|
DUP MSG-PADDR@ OVER MSG-PLEN@
|
|
ROT MSG-TO@ IDX>NAME VM-EXEC ;
|
|
Block 5021
|
|
( MSG-SEND. heat -> MSG-ALLOC's admission directly )
|
|
( (zero-heat would lose eviction-fallback density )
|
|
( comparisons), not set afterward as before. )
|
|
: MSG-SEND ( type from to paddr plen ch -- )
|
|
Q.SLOT MSG-ALLOC DUP 0= IF 2DROP 2DROP 2DROP DROP EXIT THEN
|
|
>R
|
|
MSG-SEQ @ 1+ DUP MSG-SEQ ! R@ MSG-SEQ!
|
|
R@ MSG-CH!
|
|
R@ MSG-PLEN! R@ MSG-PADDR!
|
|
R@ MSG-TO! R@ MSG-FROM! DUP R@ MSG-TYPE! R@ MSG-ORIG-TYPE!
|
|
R> DROP ;
|
|
Block 5022
|
|
( MSG-COOL-ONE/ALL: linear decay per tick )
|
|
VARIABLE MSG-SCAN
|
|
: MSG-COOL-ONE ( m -- )
|
|
DUP MSG-HEAT@ Q-DECAY Q.* SWAP MSG-HEAT! ;
|
|
: MSG-COOL-ALL ( -- )
|
|
MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-HEAT@ 0 > IF
|
|
MSG-SCAN @ MSG-COOL-ONE
|
|
THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
Block 5023
|
|
( MSG-TOTAL-HEAT )
|
|
: MSG-TOTAL-HEAT ( -- q48 )
|
|
0 MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-TYPE@ 0 <> IF
|
|
MSG-SCAN @ MSG-HEAT@ +
|
|
THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
: MSG-REDELIVER-NACKED ( -- )
|
|
MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-TYPE@ MSG-NACKED = IF
|
|
MSG-SCAN @ MSG-ORIG-TYPE@ MSG-SCAN @ MSG-TYPE! THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
Block 5024
|
|
( MSG-DELIVER-ALL )
|
|
: MSG-DELIVER-ALL ( -- )
|
|
MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-TYPE@ 0 <>
|
|
MSG-SCAN @ MSG-TYPE@ MSG-DELIVERED <> AND
|
|
MSG-SCAN @ MSG-TYPE@ MSG-NACKED <> AND IF
|
|
MSG-SCAN @ MSG-DELIVER
|
|
MSG-SCAN @ MSG-TYPE@ 0 <> IF
|
|
MSG-DELIVERED MSG-SCAN @ MSG-TYPE!
|
|
THEN
|
|
THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
Block 5025
|
|
( message reaping )
|
|
( K reap only fires at heat=0: freed K contribution is 0. )
|
|
( Force-reap not yet implemented. If added: explicit )
|
|
( K redistribution will be required here. )
|
|
: MSG-REAP ( -- )
|
|
MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-HEAT@ 0 = IF
|
|
MSG-SCAN @ MSG-TYPE@ 0 <> IF
|
|
0 MSG-SCAN @ MSG-TYPE!
|
|
MSG-SCAN @ MSG-FREE-NODE
|
|
THEN
|
|
THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
Block 5026
|
|
( channel cooling + heat aggregate )
|
|
VARIABLE CH-SCAN
|
|
: CH-COOL-ALL ( -- )
|
|
CH-ACTIVE @ CH-SCAN !
|
|
BEGIN CH-SCAN @ 0 <> WHILE
|
|
CH-SCAN @ CH-HEAT@ Q-DECAY Q.* CH-SCAN @ CH-HEAT!
|
|
CH-SCAN @ CH-NEXT@ CH-SCAN !
|
|
REPEAT ;
|
|
: CH-TOTAL-HEAT ( -- q48 )
|
|
0 CH-ACTIVE @ CH-SCAN !
|
|
BEGIN CH-SCAN @ 0 <> WHILE
|
|
CH-SCAN @ CH-HEAT@ +
|
|
CH-SCAN @ CH-NEXT@ CH-SCAN !
|
|
REPEAT ;
|
|
Block 5027
|
|
( channel reaping )
|
|
: CH-REAP-SAFE ( -- )
|
|
CH-ACTIVE @ CH-SCAN !
|
|
0 CH-ACTIVE !
|
|
BEGIN CH-SCAN @ 0 <> WHILE
|
|
CH-SCAN @ CH-NEXT@
|
|
CH-SCAN @ CH-HEAT@ 0 =
|
|
CH-SCAN @ COMMON-CH @ <> AND IF
|
|
CH-SCAN @ CH-FREE-NODE
|
|
ELSE
|
|
CH-ACTIVE @ CH-SCAN @ CH-NEXT!
|
|
CH-SCAN @ CH-ACTIVE !
|
|
THEN
|
|
CH-SCAN !
|
|
REPEAT ;
|
|
Block 5028
|
|
( COMMON + MSG-TICK (was HERMES-TICK -- generic now). )
|
|
( floor=Q.1/3. COMMON-CH VARIABLE is in block 4101. )
|
|
: COMMON-INIT ( -- )
|
|
Q.1 3 / CH-ALLOC DUP COMMON-CH !
|
|
0 OVER CH-ID! 0 OVER CH-OWNER!
|
|
CH-OPEN OVER CH-STATE!
|
|
0 OVER CH-MBRS!
|
|
CH-ACTIVE @ OVER CH-NEXT!
|
|
CH-ACTIVE ! ;
|
|
( floor-refresh is reservoir-constrained, may no-op under )
|
|
( pressure. )
|
|
: MSG-TICK ( -- )
|
|
MSG-DELIVER-ALL MSG-REDELIVER-NACKED
|
|
MSG-COOL-ALL MSG-REAP
|
|
CH-COOL-ALL CH-REAP-SAFE
|
|
Q.1 3 / COMMON-CH @ CH-HEAT! ;
|
|
Block 5029
|
|
( MSG-K (was HERMES-K -- generic now). WELCOME stays )
|
|
( behind in each VM's own init.4th. )
|
|
: MSG-K ( -- q48 )
|
|
MSG-TOTAL-HEAT CH-TOTAL-HEAT + STADIUM-RES@ +
|
|
STADIUM-WORD-HEAT + ;
|
|
Block 5030
|
|
( event compat interface. SPAWN/KILL notify-Hera is )
|
|
( automatic: see vm_physics_init/retire in mama_word_birth. )
|
|
: EVENT-EMIT ( type -- ) DROP ;
|
|
: EVENT-WAIT ( -- type )
|
|
MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-TYPE@ 0 <> IF
|
|
MSG-SCAN @ MSG-TYPE@ UNLOOP EXIT THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP 0 ;
|
|
: EVENT-DRAIN ( -- )
|
|
( no-op: MSG-REAP owns cleanup; drain breaks async ) ;
|
|
Block 5031
|
|
( channel negotiation: mint/request )
|
|
: CH-MINT-ID ( owner -- id )
|
|
MSG-SEQ @ 1+ DUP MSG-SEQ !
|
|
SWAP 32 LSHIFT OR ;
|
|
: CH-REQUEST ( type from to paddr plen -- )
|
|
COMMON-CH @ CH-STATE@ CH-OPEN = IF
|
|
COMMON-CH @ MSG-SEND
|
|
ELSE 2DROP 2DROP DROP THEN ;
|
|
Block 5032
|
|
( channel ops: accept confirm close )
|
|
: CH-ACCEPT ( -- ch|0 )
|
|
Q.SLOT CH-ALLOC DUP 0= IF EXIT THEN
|
|
1 CH-MINT-ID OVER CH-ID!
|
|
1 OVER CH-OWNER!
|
|
CH-NEGOTIATING OVER CH-STATE!
|
|
0 OVER CH-MBRS!
|
|
CH-ACTIVE @ OVER CH-NEXT!
|
|
DUP CH-ACTIVE ! ;
|
|
: CH-CONFIRM ( ch -- )
|
|
DUP CH-STATE@ CH-NEGOTIATING = IF CH-OPEN SWAP CH-STATE!
|
|
ELSE DROP THEN ;
|
|
: CH-CLOSE ( ch -- )
|
|
DUP COMMON-CH @ = IF DROP EXIT THEN
|
|
CH-CLOSING SWAP CH-STATE! ;
|
|
Block 5033
|
|
( MSG-CD-INIT (was CD-INIT -- renamed to avoid colliding )
|
|
( with Artemis's own unrelated block-subsystem CD-INIT). )
|
|
( common:msg.4th's HERMES-ACK/NACK indirection is retired: )
|
|
( every VM now has its own local MSG-ACK-LAST/NACK-LAST. )
|
|
: MSG-CD-INIT ( -- )
|
|
MSG-ARENA MSG-MAX MSG-CELLS * CELLS 0 FILL
|
|
CH-ARENA CH-MAX CH-CELLS * CELLS 0 FILL
|
|
MBR-ARENA MBR-MAX MBR-CELLS * CELLS 0 FILL
|
|
MSG-INIT-FREE
|
|
CH-INIT-FREE
|
|
MBR-INIT-FREE
|
|
0 MSG-SEQ !
|
|
0 MSG-LAST-MSG !
|
|
0 CH-ACTIVE !
|
|
COMMON-INIT
|
|
VM-NAMES-INIT ;
|
|
Block 5034
|
|
( ACK/NACK -- now purely local, no VM-EXEC indirection. )
|
|
: MSG-ACK-LAST ( -- )
|
|
MSG-LAST-MSG @ DUP 0= IF DROP EXIT THEN
|
|
0 OVER MSG-TYPE! MSG-FREE-NODE ;
|
|
: MSG-NACK-LAST ( -- )
|
|
MSG-LAST-MSG @ DUP 0= IF DROP EXIT THEN
|
|
DUP MSG-HEAT@ 2 / OVER MSG-HEAT!
|
|
MSG-NACKED SWAP MSG-TYPE! ;
|
|
Block 5035
|
|
( MSG-STATUS (was HERMES-STATUS -- generic now) )
|
|
: MSG-USED ( -- n )
|
|
0 MSG-ARENA MSG-SCAN !
|
|
MSG-MAX 0 DO
|
|
MSG-SCAN @ MSG-TYPE@ 0 <> IF 1+ THEN
|
|
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
|
|
LOOP ;
|
|
: CH-USED ( -- n )
|
|
0 CH-ACTIVE @ CH-SCAN !
|
|
BEGIN CH-SCAN @ 0 <> WHILE
|
|
1+
|
|
CH-SCAN @ CH-NEXT@ CH-SCAN !
|
|
REPEAT ;
|
|
: MSG-STATUS ( -- )
|
|
MSG-USED . ." msgs " CH-USED . ." channels" CR ;
|
|
Block 5036
|
|
( member management )
|
|
: MBR-NEXT! ( a m -- ) ! ;
|
|
: MBR-VM! ( n m -- ) 1 CELLS + ! ;
|
|
: CH-ADD-MBR ( vm ch -- )
|
|
MBR-ALLOC DUP 0= IF DROP 2DROP EXIT THEN
|
|
ROT OVER MBR-VM!
|
|
OVER CH-MBRS@ OVER MBR-NEXT!
|
|
SWAP CH-MBRS! ;
|
|
Block 5037
|
|
( Phase 2: real multi-member broadcast )
|
|
VARIABLE BC-TYPE VARIABLE BC-FROM
|
|
VARIABLE BC-PADDR VARIABLE BC-PLEN
|
|
VARIABLE BC-CH VARIABLE BC-SCAN
|
|
: MSG-BROADCAST ( type from paddr plen ch -- )
|
|
BC-CH ! BC-PLEN ! BC-PADDR ! BC-FROM ! BC-TYPE !
|
|
BC-CH @ CH-MBRS@ BC-SCAN !
|
|
BEGIN BC-SCAN @ 0<> WHILE
|
|
BC-TYPE @ BC-FROM @ BC-SCAN @ MBR-VM@
|
|
BC-PADDR @ BC-PLEN @ BC-CH @ MSG-SEND
|
|
BC-SCAN @ MBR-NEXT@ BC-SCAN !
|
|
REPEAT ;
|