From ab3ebbe227c72b745a46f9233fbfbb27477586b8 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 15 Jul 2026 23:54:13 +0200 Subject: kernel: implement fork() - sys_fork: switch to a kernel stack, bump-allocate a cart-RAM bank, copy the parent's 8 KiB bank via a WRAM bounce buffer, plant a switch-in frame so the child returns 0 to the post-fork PC, fill the child PCB (shared ROM text) - add AllocRamBank (bump allocator) + FindFreeSlot helpers - demo: init forks; parent prints P, child prints C (PCPC...); nested fork gives three distinct pids (123...) - README: document the fork mechanism, mark syscall status --- README.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'README.md') diff --git a/README.md b/README.md index bd6c5cf..2d2946c 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,30 @@ User loads `C` = syscall number, args in `DE`/`B`, then `rst $30`. Return in `A` | # | name | status | |---|---------|--------| | 0 | exit | ✅ marks zombie, reschedules | +| 1 | fork | ✅ copies the 8 KiB bank, child returns 0 | | 3 | write | ✅ `DE`=buf `B`=len → serial console | | 8 | getpid | ✅ | | 11| yield | ✅ cooperative switch | -| 1,2,4,5,6,7,9,10 | fork/read/open/close/exec/wait/kill/brk | ⛔ `ENOSYS` | +| 2,4,5,6,7,9,10 | read/open/close/exec/wait/kill/brk | ⛔ `ENOSYS` | + +### fork (`sys_fork`, src/proc.asm) + +The interesting syscall. It enters on the parent's user stack (which lives in +the `$A000-$BFFF` cart-RAM window), so before it can swap that window it +**switches to a kernel stack in WRAM0**. Then it: + +1. allocates a free PCB slot + a fresh cart-RAM bank (bump allocator), +2. copies the parent's whole 8 KiB bank → the child bank, 256 bytes at a time + through a WRAM bounce buffer (only one cart-RAM bank is visible at once), +3. plants a **switch-in frame** in the child at `Uafter-8` (`Uafter` = parent + SP at entry): the copied return address is already there, so it just zeroes + the saved `hl/de/bc/af` slots — the child resumes at the post-`fork` PC with + `A=0`, +4. fills the child PCB (shared ROM text bank, new RAM bank, parent as PPID), +5. restores the parent stack and returns the child pid. + +Verified: `init` forks a child (P/C alternate on serial); nested forks yield +three independent processes with distinct pids (`123123...`). ## The context switch (`src/hram.asm`) @@ -91,7 +111,7 @@ A real gbos would render to VRAM; serial is the zero-VRAM debug channel. ## Roadmap -- [ ] `fork`: copy parent's 8 KiB RAM bank → free bank, dup u-area, child returns 0 +- [x] `fork`: copy parent's 8 KiB RAM bank → free bank, child returns 0 - [ ] `exec`: point `PROC_ROMB` at a flashed program, reset RAM-bank layout - [ ] Preemptive scheduling: real context save in `TimerISR` → `hSwitchTo` - [ ] Use the `$D000-$DFFF` u-area (SVBK) for per-process kernel state / kstack -- cgit v1.3.1-sl0p