TonicBoxOS · architecture

Architecture & limits

A complete operating system that runs in a browser tab. A Type-1 hypervisor (tb32hv), compiled to WebAssembly, hosts a single guest: TonicBoxOS. The guest's kernel and userland are both machine code for a custom 32-bit ISA (TB32), executed by the hypervisor's CPU. The kernel runs de-privileged in guest-supervisor mode; userland reaches it only across a system-call boundary.

host tb32hv to WASM guest TB32 kernel (VS) + userland (VU) processes fork / exec / wait drivers monolithic VFS

00The stack

Four layers. Only the top one is native code; everything below it is TB32 machine code the CPU executes:

LayerWhat it is
hosta JavaScript shim: feeds input, paints an output buffer to the screen, and ticks the hypervisor while idle
hypervisortb32hv.wasm, native WebAssembly: the TB32-V CPU that interprets the guest - with a WebAssembly JIT that compiles hot code blocks at runtime - the device model (console, block device, RTC, RNG), and a small VM manager. It runs one guest, isolated by two-stage nested paging
guest kernelTB32 machine code, run in guest-supervisor (VS) mode: scheduler, process table, signals, filesystem, drivers, syscall dispatch
userlandTB32 machine code, run in guest-user (VU) mode; each process in its own isolated paged address space

Userland enters the kernel only through a SYS instruction, with the call number in r7: the CPU takes a trap and hands it to the guest kernel. Each process has its own page table, so address spaces are isolated - there is no shared memory and no virtual address that reaches another process or the kernel. Pages are allocated on first touch (demand-zero) from a physical frame pool, and fork shares them copy-on-write. A second translation stage (guest-physical to host-physical) walls the whole VM off from the host, the same way the tb32hv hypervisor isolates any guest.

Four stacked layers: the browser host (JavaScript driver) exchanges bytes and MMIO with the tb32hv.wasm Type-1 hypervisor, which interprets one guest under two-stage nested paging. Inside the guest, a kernel runs in VS mode (scheduler, filesystem, drivers, syscall dispatch); below it, in VU mode across a syscall boundary, init (PID 1) forks and execs syslogd, the login shell -sh, and commands, each in its own isolated paged address space.
Host, hypervisor, and an isolated guest whose kernel and userland run at different privilege levels.

01Processes

fork copies a process copy-on-write into a fresh address space; exec replaces the image in place; wait reaps children. Scheduling is preemptive round-robin: a hardware timer preempts each runnable process after a fixed instruction quantum, so daemons and background jobs advance while the shell waits at a prompt.

Boot enters init as PID 1: it spawns the services and, on the interactive console, a getty-style login that authenticates against /etc/shadow and drops privileges to your login shell (the system is multi-user - root, tonicbox, dev - with euid-enforced permissions). init then reaps orphans for the rest of the session. Signals are complete: handlers, masks, default actions, and job control. PID 1 ignores any signal for which it has no handler installed, so userland cannot terminate it.

Processes talk over real pipes, and the console has an in-kernel termios line discipline (cooked/raw modes, echo, editing). The shell is a session leader that puts each job in its own process group and hands the terminal to the foreground job, so Ctrl‑C, Ctrl‑Z, and fg/bg behave the way they do on a real Unix.

PieceWhat it is
initPID 1; spawns services + the login shell, reaps orphans
syslogda daemon draining the kernel log to /var/log/messages
schedulerpreemptive round-robin over a pool of process slots
signalskill, handlers, pause, job control

02Kernel & VFS

A monolithic VFS, Linux-style: a mount table routes each path to a filesystem type, and file operations dispatch from there.

A file syscall (open, read, write, stat, unlink, link) enters the VFS, which looks up the mount table and dispatches to one of three filesystem types: ramfs (an inode filesystem with a superblock, inode table, block bitmap, data blocks, dentry directories, and symlinks plus hard links), devfs (/dev nodes, which route to the char-driver registry keyed by major number), or procfs (content generated on read).
One VFS entry point; three filesystem types; devices reach the driver registry.

03Toolchain

Self-hosting. TBC (a C subset) compiles to TB32 assembly, and the assembler emits a TBX executable the kernel loads. The compiler and assembler are themselves TB32 programs that run inside the OS, so building and debugging happen entirely in the terminal.

04Limits

Structures are fixed-size and in-memory. The main limits:

AreaLimit
processesa fixed pool of process slots; beyond it, spawns are refused rather than queued
memoryeach process has its own paged virtual address space (4 KiB pages, demand-zero, copy-on-write fork, mmap/mprotect); pages are backed by a shared physical frame pool, so total live memory across all processes is bounded by the pool
filesysteman inode/block filesystem on a virtual block device, with a fixed inode count and a fixed number of data blocks; state is per-session (reset on reload, or saved to the browser)
argumentsa command takes a bounded number of arguments
streamsa pipe is a bounded ring buffer; a full pipe blocks the writer until the reader drains it, so large streams flow through without loss
compilerTBC is a subset: no floats or structs. It does have enums, typedef, multidimensional arrays with brace initializers, a #if/macro preprocessor, and a malloc/mem*/str* prelude; function pointers are supported (untyped)
shellfunctions are scoped to a single command line and do not persist across prompts