; ============================================================================= ; sched.asm - round-robin scheduler + yield + timer stub ; ============================================================================= INCLUDE "include/gbos.inc" SECTION "sched", ROM0 ; ----------------------------------------------------------------------------- ; SchedInit - prime the round-robin cursor so the first pick lands on slot 0. ; ----------------------------------------------------------------------------- SchedInit:: ld a, MAX_PROCS - 1 ld [wSchedNext], a ret ; ----------------------------------------------------------------------------- ; SchedRunFirst - hand control to the first runnable task. Never returns; the ; kernel-init context is saved into wKernelPCB and simply abandoned. ; ----------------------------------------------------------------------------- SchedRunFirst:: ld hl, wKernelPCB ld a, l ld [wCurProc], a ld a, h ld [wCurProc+1], a call FindNextReady ; DE = &first ready PCB jp hSwitchTo ; ----------------------------------------------------------------------------- ; SchedYield - cooperative switch to the next runnable task. Returns to the ; caller when this task is eventually rescheduled. ; ----------------------------------------------------------------------------- SchedYield:: call FindNextReady ; DE = &next PCB call hSwitchTo ret ; ----------------------------------------------------------------------------- ; FindNextReady - round-robin from wSchedNext. out: DE = &PCB (updates cursor) ; Scaffold: assumes at least one PS_READY task exists. ; ----------------------------------------------------------------------------- FindNextReady:: ld a, [wSchedNext] ld b, MAX_PROCS .scan inc a cp MAX_PROCS jr c, .nowrap xor a .nowrap push af ; save candidate slot call PcbPtr ; DE = &PCB[slot] (preserves BC) ld a, [de] ; state cp PS_READY jr z, .found pop af ; restore candidate slot dec b jr nz, .scan ; nothing ready: fall back to slot 0 (idle behavior) xor a call PcbPtr ret .found pop af ; A = chosen slot ld [wSchedNext], a call PcbPtr ; DE = &PCB ret ; ----------------------------------------------------------------------------- ; TimerISR - preemption hook (TODO). A real preemptive switch must save the ; interrupted context and call hSwitchTo from here. For now the demo is ; cooperative (tasks call SYS_YIELD), so we just acknowledge and return. ; ----------------------------------------------------------------------------- TimerISR:: reti