aboutsummaryrefslogtreecommitdiffstats
path: root/src/tasks.asm
blob: 028d07430b5c5432efc8c5f47677069a5b7a283b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
; =============================================================================
; tasks.asm - init exercises the full process lifecycle.
;
; 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
    or a
    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

.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_WORKER
    ld c, SYS_EXEC
    rst $30                 ; never returns