aboutsummaryrefslogtreecommitdiffstats
path: root/src/tasks.asm
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-16 00:12:43 +0200
committeruser <user@clank>2026-07-16 00:12:43 +0200
commit19a2b63bab71b796ee456b3ae8bec1a2ab297158 (patch)
tree49b1effd335d47e859002903caea337fea27e1b9 /src/tasks.asm
parentkernel: implement exec() (diff)
downloadgbos-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 '')
-rw-r--r--src/tasks.asm64
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