/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. */ /** * session.c - Per-VM session bookkeeping (FABRIC-3.md §H.12 steps 2-3) * * Slot table sized from stadium_max_vm_count() at session_boot_init() time, * mirroring stadium.c's own StadiumVMQuota table (kmalloc'd to a * budget-computed count, not a fixed compile-time array -- population isn't * knowable in advance, same reasoning stadium.c's own history already * settled). No callers yet; wiring into the boot sequence and into * stadium_birth_hera()/capsule_birth.c's admission path are later * §H.12 steps. * * session_set_pinned()/session_is_pinned() (step 3) are the pin-authority * choke point -- see their own doc comments in session.h for the * authoritative-session-mirrored-Stadium-bit split. */ #ifdef __STARKERNEL__ #include "starkernel/session.h" #include "starkernel/vm/stadium.h" #include "starkernel/kmalloc.h" static Session *g_sessions = (Session *)0; static size_t g_session_slots = 0; /* capacity, from stadium_max_vm_count() */ static size_t g_session_count = 0; /* slots actually in use, 0..g_session_slots */ int session_boot_init(void) { size_t max_vm_count = stadium_max_vm_count(); Session *slots; size_t i; if (max_vm_count == 0) return -1; /* Stadium not yet initialized */ slots = (Session *)kmalloc(max_vm_count * sizeof(Session)); if (!slots) return -1; for (i = 0; i < max_vm_count; i++) { uint8_t *raw = (uint8_t *)&slots[i]; size_t j; for (j = 0; j < sizeof(Session); j++) raw[j] = 0; slots[i].vm_id = vm_uuid_none(); slots[i].parent = vm_uuid_none(); } g_sessions = slots; g_session_slots = max_vm_count; g_session_count = 0; return 0; } Session *session_find(VMUuid vm_id) { size_t i; if (!g_sessions) return (Session *)0; for (i = 0; i < g_session_slots; i++) { if (!vm_uuid_is_none(g_sessions[i].vm_id) && vm_uuid_equal(g_sessions[i].vm_id, vm_id)) { return &g_sessions[i]; } } return (Session *)0; } Session *session_register(VMUuid vm_id, VMUuid parent, const char *name) { size_t i; Session *slot = (Session *)0; if (!g_sessions) return (Session *)0; if (session_find(vm_id)) return (Session *)0; /* already registered */ for (i = 0; i < g_session_slots; i++) { if (vm_uuid_is_none(g_sessions[i].vm_id)) { slot = &g_sessions[i]; break; } } if (!slot) return (Session *)0; /* table full */ slot->vm_id = vm_id; slot->parent = parent; slot->pinned = 0; slot->stadium_cell = SESSION_STADIUM_CELL_NONE; { size_t j = 0; if (name) { for (; j < SESSION_NAME_BUF - 1u && name[j]; j++) slot->name[j] = name[j]; } slot->name[j] = '\0'; } { uint8_t *raw = (uint8_t *)&slot->identity; size_t j; for (j = 0; j < sizeof(VMIdentity); j++) raw[j] = 0; } g_session_count++; return slot; } void session_set_pinned(VMUuid vm_id, int pinned) { Session *s = session_find(vm_id); StadiumCell *cells; if (!s) return; s->pinned = pinned ? 1 : 0; if (s->stadium_cell == SESSION_STADIUM_CELL_NONE) return; if (s->stadium_cell >= stadium_cell_count()) return; cells = stadium_cells(); if (!cells) return; if (pinned) { cells[s->stadium_cell].header.flags |= STADIUM_FLAG_PIN; } else { cells[s->stadium_cell].header.flags &= (uint8_t)~STADIUM_FLAG_PIN; } } int session_is_pinned(VMUuid vm_id) { Session *s = session_find(vm_id); if (!s) return 0; return s->pinned; } #endif /* __STARKERNEL__ */