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 /src/tasks.asm | |
| 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 'src/tasks.asm')
| -rw-r--r-- | src/tasks.asm | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/src/tasks.asm b/src/tasks.asm index 0b5276d..028d074 100644 --- a/src/tasks.asm +++ b/src/tasks.asm @@ -1,27 +1,67 @@ ; ============================================================================= -; tasks.asm - the init task demonstrates fork() + exec(). +; tasks.asm - init exercises the full process lifecycle. ; -; init forks; the parent exec()s PROG_PING (ROM bank 2), the child exec()s -; PROG_PONG (ROM bank 3). Both program images are ORG'd at $4000, so the output -; "1212..." proves each process runs from its own ROM bank via PROC_ROMB - not -; from shared ROM0. +; init fork()s three children; each child exec()s PROG_WORKER, which prints 'w' +; and exit()s with its pid as the status. init then wait()s in a loop, printing +; 'R' + the reaped pid digit for each child, until wait() returns $FF (no more +; children), then prints '!' and idles. This drives fork + exec + exit + wait + +; zombie reaping + cart-RAM bank recycling. +; +; The fork counter lives at $A000 (bottom of init's own RAM bank) because the +; register file does not survive a fork() call. ; ============================================================================= INCLUDE "include/gbos.inc" +DEF ASCII0 EQU $30 ; '0', added to a pid to print it as a digit +DEF CH_R EQU $52 ; 'R' +DEF CH_BANG EQU $21 ; '!' + SECTION "tasks", ROM0 TaskInit:: + ld a, 3 + ld [$A000], a ; children left to spawn + +.forkloop ld c, SYS_FORK - rst $30 ; A = child pid (parent) or 0 (child) + rst $30 or a - jr z, .child + jr z, .child ; A==0 -> we are the child + ; parent: one more child spawned + ld a, [$A000] + dec a + ld [$A000], a + jr nz, .forkloop -.parent - ld b, PROG_PING - ld c, SYS_EXEC - rst $30 ; never returns +.waitloop + ld c, SYS_WAIT + rst $30 ; A = reaped pid (B = code), or $FF if none left + cp $FF + jr z, .done + ; print 'R' then the reaped pid as a digit + push af + ld a, CH_R + ld [$FF01], a + ld a, $81 + ld [$FF02], a + pop af + add ASCII0 + ld [$FF01], a + ld a, $81 + ld [$FF02], a + jr .waitloop + +.done + ld a, CH_BANG + ld [$FF01], a + ld a, $81 + ld [$FF02], a +.idle + ld c, SYS_YIELD + rst $30 + jr .idle .child - ld b, PROG_PONG + ld b, PROG_WORKER ld c, SYS_EXEC rst $30 ; never returns |
