diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/kdata.asm | 3 | ||||
| -rw-r--r-- | src/proc.asm | 18 | ||||
| -rw-r--r-- | src/programs.asm | 16 | ||||
| -rw-r--r-- | src/syscall.asm | 168 |
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 |
