diff options
| author | user <user@clank> | 2026-07-15 23:54:13 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-15 23:54:13 +0200 |
| commit | ab3ebbe227c72b745a46f9233fbfbb27477586b8 (patch) | |
| tree | d71f87605d17c5653f34ebcdef3941f898cd5b91 /README.md | |
| parent | gbos scaffold: working cooperative microkernel (verified ABAB in emulator) (diff) | |
| download | gbos-ab3ebbe227c72b745a46f9233fbfbb27477586b8.tar.gz gbos-ab3ebbe227c72b745a46f9233fbfbb27477586b8.tar.xz gbos-ab3ebbe227c72b745a46f9233fbfbb27477586b8.zip | |
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
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 24 |
1 files changed, 22 insertions, 2 deletions
@@ -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 |
