aboutsummaryrefslogtreecommitdiffstats
path: root/src/sched.asm
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-15 23:44:28 +0200
committeruser <user@clank>2026-07-15 23:44:28 +0200
commitde725da74db5cba0f9bfd0755269e1683423d87b (patch)
treedc39eca9fbd290393ed51de31eee5e4bd6af8375 /src/sched.asm
downloadgbos-de725da74db5cba0f9bfd0755269e1683423d87b.tar.gz
gbos-de725da74db5cba0f9bfd0755269e1683423d87b.tar.xz
gbos-de725da74db5cba0f9bfd0755269e1683423d87b.zip
gbos scaffold: working cooperative microkernel (verified ABAB in emulator)
- fix ClearKernelRAM clobbering the kernel stack (only clear $C000-$CBFF) - fix SyscallTrap clobbering DE (buffer arg) during table dispatch - README: run via ~/dev/gbc --headless; note bring-up bugs
Diffstat (limited to 'src/sched.asm')
-rw-r--r--src/sched.asm75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/sched.asm b/src/sched.asm
new file mode 100644
index 0000000..c871f7a
--- /dev/null
+++ b/src/sched.asm
@@ -0,0 +1,75 @@
+; =============================================================================
+; 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