aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kdata.asm3
-rw-r--r--src/proc.asm18
-rw-r--r--src/programs.asm16
-rw-r--r--src/syscall.asm168
4 files changed, 202 insertions, 3 deletions
diff --git a/src/kdata.asm b/src/kdata.asm
index ea18756..b299021 100644
--- a/src/kdata.asm
+++ b/src/kdata.asm
@@ -46,3 +46,6 @@ wFsSlot:: DS 1
wFsByte:: DS 1
wFsOFPtr:: DS 2
wKChar:: DS 1 ; scratch for KPutc
+wKillParent::DS 1 ; scratch for sys_kill
+wPsBuf:: DS 2 ; scratch for sys_ps
+wPnStart:: DS 2 ; scratch for sys_progname
diff --git a/src/proc.asm b/src/proc.asm
index ab1c807..cd79160 100644
--- a/src/proc.asm
+++ b/src/proc.asm
@@ -224,7 +224,9 @@ ProcCreate::
ld [hl+], a ; PROC_EXIT
ld a, STD_CONSOLE
ld [hl+], a ; PROC_STDIN = console
- ld [hl], a ; PROC_STDOUT = console
+ ld [hl+], a ; PROC_STDOUT = console
+ ld a, $FF
+ ld [hl], a ; PROC_PROG = none
; build the initial stack frame in the task's RAM bank
ld a, [wTmpEntry]
@@ -453,7 +455,10 @@ sys_fork::
ld [hl+], a ; child STDIN = parent STDIN
inc de
ld a, [de]
- ld [hl], a ; child STDOUT = parent STDOUT
+ ld [hl+], a ; child STDOUT = parent STDOUT
+ inc de
+ ld a, [de]
+ ld [hl], a ; child PROC_PROG = parent PROC_PROG
; ---- return to the parent with child pid ----
ld a, [wForkUserSP]
@@ -484,6 +489,15 @@ sys_fork::
; our demo programs keep no pre-initialized RAM.
; =============================================================================
sys_exec::
+ ; record the running program id in the PCB (for ps)
+ ld a, [wCurProc]
+ add PROC_PROG
+ ld l, a
+ ld a, [wCurProc+1]
+ adc 0
+ ld h, a
+ ld a, b
+ ld [hl], a
; HL = &ProgramTable[B] = ProgramTable + B*4
ld hl, ProgramTable
ld a, b
diff --git a/src/programs.asm b/src/programs.asm
index 1a7092e..f21d40b 100644
--- a/src/programs.asm
+++ b/src/programs.asm
@@ -88,6 +88,12 @@ ProgSave:
SECTION "prog_rm", ROMX[$4000], BANK[17]
ProgRm:
INCBIN "c/rm.bin"
+SECTION "prog_ps", ROMX[$4000], BANK[18]
+ProgPs:
+ INCBIN "c/ps.bin"
+SECTION "prog_kill", ROMX[$4000], BANK[19]
+ProgKill:
+ INCBIN "c/kill.bin"
; -----------------------------------------------------------------------------
; PROG_SH (bank 3) - the shell, now written in C (c/sh.c): parses >/</| and
@@ -162,6 +168,10 @@ ProgramTable::
dw ProgSave
db LOW(BANK(ProgRm)), HIGH(BANK(ProgRm))
dw ProgRm
+ db LOW(BANK(ProgPs)), HIGH(BANK(ProgPs))
+ dw ProgPs
+ db LOW(BANK(ProgKill)), HIGH(BANK(ProgKill))
+ dw ProgKill
; -----------------------------------------------------------------------------
; NameTable (ROM0) - command name -> program id, searched by sys_lookup.
@@ -198,4 +208,10 @@ NameTable::
db PROG_SAVE
db "rm", 0
db PROG_RM
+ db "sh", 0
+ db PROG_SH
+ db "ps", 0
+ db PROG_PS
+ db "kill", 0
+ db PROG_KILL
db 0
diff --git a/src/syscall.asm b/src/syscall.asm
index f149a76..0b47c05 100644
--- a/src/syscall.asm
+++ b/src/syscall.asm
@@ -43,7 +43,7 @@ SyscallTable:
dw sys_exec ; 6 EXEC
dw sys_wait ; 7 WAIT
dw sys_getpid ; 8 GETPID
- dw sys_nosys ; 9 KILL (TODO)
+ dw sys_kill ; 9 KILL
dw sys_nosys ; 10 BRK (TODO)
dw sys_yield ; 11 YIELD
dw sys_getb ; 12 GETB
@@ -54,6 +54,8 @@ SyscallTable:
dw sys_setin ; 17 SETIN
dw sys_setout ; 18 SETOUT
dw sys_lookup ; 19 LOOKUP
+ dw sys_ps ; 20 PS
+ dw sys_progname ; 21 PROGNAME
; -----------------------------------------------------------------------------
sys_nosys:
@@ -388,3 +390,167 @@ sys_wait:
.nochild
ld a, $FF
ret
+
+; =============================================================================
+; sys_kill(B = pid) -> A = 0 ok / $FF fail. pid 1 (init/shell) is immortal.
+; Terminates the target: mark zombie, reparent its children to init, wake its
+; parent if blocked in wait. If we killed ourselves, schedule away forever.
+; =============================================================================
+sys_kill::
+ ld a, b
+ cp INIT_PID
+ jr z, .fail ; init is immortal
+ call FindPcbByPid ; A=pid -> DE=&PCB, CF if not found (B preserved=pid)
+ jr c, .fail
+ ld a, [de] ; state
+ cp PS_FREE
+ jr z, .fail
+ cp PS_ZOMBIE
+ jr z, .fail ; already dead
+ ; mark ZOMBIE
+ ld a, PS_ZOMBIE
+ ld [de], a
+ ; PROC_EXIT = KILL_CODE
+ ld a, e
+ add PROC_EXIT
+ ld l, a
+ ld a, d
+ adc 0
+ ld h, a
+ ld a, KILL_CODE
+ ld [hl], a
+ ; victim's parent pid
+ ld a, e
+ add PROC_PARENT
+ ld l, a
+ ld a, d
+ adc 0
+ ld h, a
+ ld a, [hl]
+ ld [wKillParent], a
+ ; reparent victim's children to init (B still = victim pid)
+ ld a, b
+ ld [wExitMyPid], a
+ call ReparentToInit
+ ; wake victim's parent if it is blocked in wait()
+ ld a, [wKillParent]
+ call FindPcbByPid
+ jr c, .maybe_self
+ ld a, [de]
+ cp PS_BLOCKED
+ jr nz, .maybe_self
+ ld a, PS_READY
+ ld [de], a
+.maybe_self
+ ; if the victim is the current process, don't return to it
+ ld a, [wCurProc]
+ add PROC_PID
+ ld l, a
+ ld a, [wCurProc+1]
+ adc 0
+ ld h, a
+ ld a, [wExitMyPid]
+ cp [hl]
+ jr nz, .ok
+.dead
+ call SchedYield
+ jr .dead
+.ok
+ xor a
+ ret
+.fail
+ ld a, $FF
+ ret
+
+; =============================================================================
+; sys_ps(B = slot, DE = buf[3]) -> A = 1 if used (buf = pid,state,prog), else 0
+; =============================================================================
+sys_ps::
+ ld a, e
+ ld [wPsBuf], a
+ ld a, d
+ ld [wPsBuf+1], a
+ ld a, b
+ cp MAX_PROCS
+ jr nc, .no
+ call PcbPtr ; DE = &PCB[slot]
+ ld a, [de] ; state
+ cp PS_FREE
+ jr z, .no
+ ld a, [wPsBuf]
+ ld l, a
+ ld a, [wPsBuf+1]
+ ld h, a ; HL = buf
+ push de ; PCB
+ ld a, e
+ add PROC_PID
+ ld e, a
+ ld a, d
+ adc 0
+ ld d, a
+ ld a, [de] ; pid
+ ld [hl+], a
+ pop de
+ push de
+ ld a, [de] ; state
+ ld [hl+], a
+ pop de
+ ld a, e
+ add PROC_PROG
+ ld e, a
+ ld a, d
+ adc 0
+ ld d, a
+ ld a, [de] ; prog id
+ ld [hl], a
+ ld a, 1
+ ret
+.no
+ xor a
+ ret
+
+; =============================================================================
+; sys_progname(B = id, DE = namebuf) - copy the command name for a program id.
+; =============================================================================
+sys_progname::
+ ld hl, NameTable
+.l
+ ld a, [hl]
+ or a
+ jr z, .none
+ ld a, l
+ ld [wPnStart], a
+ ld a, h
+ ld [wPnStart+1], a
+.sk
+ ld a, [hl+]
+ or a
+ jr nz, .sk ; HL now at the id byte
+ ld a, [hl]
+ cp b
+ jr z, .match
+ inc hl ; skip id -> next entry
+ jr .l
+.match
+ ld a, [wPnStart]
+ ld l, a
+ ld a, [wPnStart+1]
+ ld h, a
+ ld b, 8
+.cp
+ ld a, [hl+]
+ ld [de], a
+ inc de
+ or a
+ jr z, .done
+ dec b
+ jr nz, .cp
+.done
+ ret
+.none
+ ld a, $3F ; '?'
+ ld [de], a
+ inc de
+ xor a
+ ld [de], a
+ ret