Channel table + common channel, inert (B1) -- FABRIC-3.6.md task 3.2
Adds SkHermesChannel: a channel is an index into a boot-time, stadium_max_vm_count()-sized table (same sizing pattern task 3.1 established for the switch table -- no separate numeric rule was ruled for this table, so task 3.1's bound is extended directly, flagged as such rather than restated as a new ruling). No name field, mirroring messaging.4th's own nameless CH-ARENA. The common channel (index 0) is created at boot and permanent. Hera subscribes explicitly in kernel_main.c (she is the one VM never born through capsule_birth_baby()); every other VM -- Tripod fleet and future WIREBIND identities alike -- subscribes inside capsule_birth_baby() itself, the single choke point every other birth already passes through. Inert: no publish, no dispatch, no ACK/NACK, no ACL hook (tasks 3.3, 3.6, 3.7). Verified live on all three architectures: channel table sized to 50/202/50 slots (matching switch-signal's own per-arch sizing), common-channel fleet self-test confirms all four Tripod members are members, and a synthetic create/subscribe/unsubscribe/ destroy round-trip against a private topic passes, including refusing to destroy the common channel. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c19ef365fe
commit
a4afdfa591
@@ -48,8 +48,27 @@
|
||||
#include "starkernel/vm/kernel_hermes.h"
|
||||
#include "starkernel/vm/stadium.h"
|
||||
#include "starkernel/q48_16.h"
|
||||
#include "starkernel/kmalloc.h"
|
||||
#include "console.h"
|
||||
|
||||
/* Freestanding: no libc printf. Prints an unsigned decimal, no leading
|
||||
* zeros -- same small helper stadium.c/capsule_vm_switch_signal.c each
|
||||
* carry their own copy of. */
|
||||
static void console_put_u64(uint64_t v) {
|
||||
char buf[21];
|
||||
int i = 20;
|
||||
buf[20] = '\0';
|
||||
if (v == 0) {
|
||||
console_puts("0");
|
||||
return;
|
||||
}
|
||||
while (v > 0 && i > 0) {
|
||||
buf[--i] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
console_puts(&buf[i]);
|
||||
}
|
||||
|
||||
static SkHermesMessage sk_hermes_msgs[SK_HERMES_MSG_MAX];
|
||||
|
||||
/* Task 2.4 (item 28), FABRIC-3.5.md SXXXVII.3/SXL.4's four counters.
|
||||
@@ -247,4 +266,130 @@ int sk_hermes_decay(SkHermesMessage *msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Task 3.2 (item 27, B1 / FABRIC-3.5.md SXLV.1): the channel table. See
|
||||
* kernel_hermes.h's own doc comment on this section for scope and sizing
|
||||
* reasoning. */
|
||||
static SkHermesChannel *sk_hermes_channels = (SkHermesChannel *)0;
|
||||
static int sk_hermes_channel_capacity_val = 0;
|
||||
|
||||
int sk_hermes_channels_boot_init(void) {
|
||||
size_t max_vm_count = stadium_max_vm_count();
|
||||
SkHermesChannel *table;
|
||||
size_t i;
|
||||
|
||||
if (max_vm_count == 0) return -1; /* Stadium not yet initialized */
|
||||
|
||||
table = (SkHermesChannel *)kmalloc(max_vm_count * sizeof(SkHermesChannel));
|
||||
if (!table) return -1;
|
||||
|
||||
for (i = 0; i < max_vm_count; i++) {
|
||||
memset(&table[i], 0, sizeof(SkHermesChannel));
|
||||
}
|
||||
|
||||
/* The common channel exists from boot (SXLV.1), empty -- VMs join it
|
||||
* at birth (kernel_main.c/capsule_birth.c task 3.2 wiring), not here. */
|
||||
table[SK_HERMES_CHANNEL_COMMON].in_use = 1;
|
||||
|
||||
sk_hermes_channels = table;
|
||||
sk_hermes_channel_capacity_val = (int)max_vm_count;
|
||||
|
||||
console_puts("Kernel-Hermes: ");
|
||||
console_put_u64((uint64_t)max_vm_count);
|
||||
console_println(" channel slots");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_capacity(void) {
|
||||
return sk_hermes_channel_capacity_val;
|
||||
}
|
||||
|
||||
static int channel_valid(int channel_id) {
|
||||
return sk_hermes_channels &&
|
||||
channel_id >= 0 &&
|
||||
channel_id < sk_hermes_channel_capacity_val &&
|
||||
sk_hermes_channels[channel_id].in_use;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_create(void) {
|
||||
int i;
|
||||
|
||||
if (!sk_hermes_channels) return -1;
|
||||
|
||||
/* Index 0 is always in_use (the common channel), so this scan never
|
||||
* returns it -- start at 1 purely as a scan-cost micro-optimisation,
|
||||
* not for correctness (the in_use check alone would already skip it). */
|
||||
for (i = 1; i < sk_hermes_channel_capacity_val; i++) {
|
||||
if (!sk_hermes_channels[i].in_use) {
|
||||
memset(&sk_hermes_channels[i], 0, sizeof(SkHermesChannel));
|
||||
sk_hermes_channels[i].in_use = 1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_destroy(int channel_id) {
|
||||
if (channel_id == SK_HERMES_CHANNEL_COMMON) return -1; /* permanent, SXLV.1 */
|
||||
if (!channel_valid(channel_id)) return -1;
|
||||
|
||||
memset(&sk_hermes_channels[channel_id], 0, sizeof(SkHermesChannel));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_subscribe(int channel_id, VMUuid vm_id) {
|
||||
SkHermesMembership *m;
|
||||
size_t i;
|
||||
|
||||
if (!channel_valid(channel_id)) return -1;
|
||||
|
||||
m = &sk_hermes_channels[channel_id].membership;
|
||||
for (i = 0; i < m->count; i++) {
|
||||
if (vm_uuid_equal(m->members[i], vm_id)) return -1; /* already a member */
|
||||
}
|
||||
if (m->count >= SK_HERMES_MEMBER_MAX) return -1;
|
||||
|
||||
m->members[m->count] = vm_id;
|
||||
m->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_unsubscribe(int channel_id, VMUuid vm_id) {
|
||||
SkHermesMembership *m;
|
||||
size_t i;
|
||||
|
||||
if (!channel_valid(channel_id)) return -1;
|
||||
|
||||
m = &sk_hermes_channels[channel_id].membership;
|
||||
for (i = 0; i < m->count; i++) {
|
||||
if (vm_uuid_equal(m->members[i], vm_id)) {
|
||||
size_t j;
|
||||
for (j = i; j < m->count - 1; j++) {
|
||||
m->members[j] = m->members[j + 1];
|
||||
}
|
||||
m->count--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1; /* not a member */
|
||||
}
|
||||
|
||||
int sk_hermes_channel_is_member(int channel_id, VMUuid vm_id) {
|
||||
SkHermesMembership *m;
|
||||
size_t i;
|
||||
|
||||
if (!channel_valid(channel_id)) return 0;
|
||||
|
||||
m = &sk_hermes_channels[channel_id].membership;
|
||||
for (i = 0; i < m->count; i++) {
|
||||
if (vm_uuid_equal(m->members[i], vm_id)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sk_hermes_channel_member_count(int channel_id) {
|
||||
if (!channel_valid(channel_id)) return -1;
|
||||
return (int)sk_hermes_channels[channel_id].membership.count;
|
||||
}
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
Reference in New Issue
Block a user