diff options
| author | user <user@clank> | 2026-07-16 00:12:43 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-16 00:12:43 +0200 |
| commit | 19a2b63bab71b796ee456b3ae8bec1a2ab297158 (patch) | |
| tree | 49b1effd335d47e859002903caea337fea27e1b9 /README.md | |
| parent | kernel: implement exec() (diff) | |
| download | gbos-19a2b63bab71b796ee456b3ae8bec1a2ab297158.tar.gz gbos-19a2b63bab71b796ee456b3ae8bec1a2ab297158.tar.xz gbos-19a2b63bab71b796ee456b3ae8bec1a2ab297158.zip | |
kernel: complete the process lifecycle (exit/wait/reap + bank free list)
- exit(): zombie + status, reparent orphans to init, wake blocked parent,
schedule away forever (resources reclaimed by the reaper)
- wait(): scan for a zombie child; reap (free cart-RAM bank + PCB slot) and
return pid/code; block PS_BLOCKED + yield if children still live; $FF if none
- cart-RAM banks are now a free list (wBankUsed bitmap): AllocRamBank/FreeRamBank
- scheduler: FindNextReady returns carry when nothing runnable; yield idles
instead of blindly picking slot 0
- helpers: FindPcbByPid, ReparentToInit
- demo: init forks 3 workers -> exec -> exit(pid) -> wait/reap => wwwR2R3R4!
verified bank recycling with 6 workers over 3 banks (w2w3w4w5w6w7)
- README: document the lifecycle + syscall status
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 28 |
1 files changed, 26 insertions, 2 deletions
@@ -45,13 +45,35 @@ User loads `C` = syscall number, args in `DE`/`B`, then `rst $30`. Return in `A` | # | name | status | |---|---------|--------| -| 0 | exit | ✅ marks zombie, reschedules | +| 0 | exit | ✅ zombie + reparent orphans + wake waiter | | 1 | fork | ✅ copies the 8 KiB bank, child returns 0 | | 3 | write | ✅ `DE`=buf `B`=len → serial console | | 6 | exec | ✅ `B`=program id → maps ROM text bank, jumps in | +| 7 | wait | ✅ blocks; reaps a zombie child → `A`=pid `B`=code | | 8 | getpid | ✅ | | 11| yield | ✅ cooperative switch | -| 2,4,5,7,9,10 | read/open/close/wait/kill/brk | ⛔ `ENOSYS` | +| 2,4,5,9,10 | read/open/close/kill/brk | ⛔ `ENOSYS` | + +### Process lifecycle (exit / wait / reaping) + +The classic Unix zombie/reap dance, adapted to banked memory: + +- **`exit(code)`** sets `PS_ZOMBIE` + status, **reparents** any children to init + (pid 1), **wakes** the parent if it's blocked in `wait()`, then schedules + away forever. Its resources are freed by the reaper, not here. +- **`wait()`** scans for a `PS_ZOMBIE` child. Found → **reap**: free its + cart-RAM bank (back to the allocator) and its PCB slot, return pid + code. + Children exist but none dead → set self `PS_BLOCKED` and yield, retry on wake. + No children → return `$FF` (`ECHILD`). +- The scheduler skips non-`READY` procs; `FindNextReady` returns carry when + nothing is runnable so `yield` just keeps the caller running (idle). +- **Cart-RAM banks are a free list** (`wBankUsed` bitmap): `AllocRamBank` / + `FreeRamBank`. Verified by running 6 workers through only 3 child banks + (`w2w3w4w5w6w7`) — each reaped bank is recycled by the next `fork`. + +Lifecycle demo (`tasks.asm`): init forks 3 workers, each `exec`s PROG_WORKER +(prints `w`, exits with its pid), init `wait`s and reaps all three → +`wwwR2R3R4!`. ### exec (`sys_exec`, src/proc.asm + programs.asm) @@ -131,7 +153,9 @@ A real gbos would render to VRAM; serial is the zero-VRAM debug channel. - [x] `fork`: copy parent's 8 KiB RAM bank → free bank, child returns 0 - [x] `exec`: point `PROC_ROMB` at a program in a ROM bank, reset stack, enter +- [x] `exit` / `wait` / zombie reaping + cart-RAM bank recycling (free list) - [ ] `exec` refinement: copy `.data` from ROM + zero `.bss` for RW globals +- [ ] a real shell program: `fork`+`exec`+`wait` driven from the serial console - [ ] Preemptive scheduling: real context save in `TimerISR` → `hSwitchTo` - [ ] Use the `$D000-$DFFF` u-area (SVBK) for per-process kernel state / kstack - [ ] `brk`/heap allocator inside the task bank (heap up, stack down, collision = ENOMEM) |
