Context switching and the CPU layer¶
arch/cpu.ik is the thin architecture layer the scheduler stands on: it
switches between process contexts and brackets critical sections. Everything
above it (the scheduler, the syscalls) is portable; the AVR-specific register
and stack handling is concentrated here.
Switching contexts¶
A context switch saves the running process’s stack pointer, then loads the next one. Because the AVR keeps the call/return state and saved registers on the stack, restoring a stack pointer restores a whole suspended process — it resumes exactly where it last switched out.
- @ctx_switch($old_sp_ptr: u16, $new_sp: u16)¶
Switch contexts with interrupts masked: save the current stack pointer to
*$old_sp_ptrand load$new_sp. The register save/restore around the stack-pointer swap is done by the@swtchprimitive;@ctx_switchwraps it in@cli/@seiso the swap is atomic.
The scheduler calls this to enter a process and, when that process yields,
control returns here and then back to the scheduler — each side resumes after
its own @ctx_switch.
Bootstrapping a new process¶
A process that has never run has no saved context yet. @proc_start calls
@ctx_bootstrap to fake one, so the very first switch into the process
“returns” into its entry function.
- @ctx_bootstrap($stack_top: u16, $sp_slot: u16, $entry: u16)¶
Lay out a fresh stack at
$stack_topso the first@ctx_switchinto it begins executing$entry: push$entryas a return address (a word address, hence$entry * 2bytes, stored high byte first), and record the resulting stack pointer ($stack_top - 2) in the process’s saved-SP slot at$sp_slot.
Critical sections¶
Some sequences must not be interrupted — notably a context switch, or a read-modify-write of shared kernel state. The pair below brackets such a section and, crucially, restores the previous interrupt state rather than unconditionally re-enabling interrupts, so critical sections nest correctly.
- @irq_disable() -> u8¶
Disable interrupts and return whether they were enabled (1) or already disabled (0), read from the
Iflag (bit 7) ofSREG.
- @irq_restore($were_on: u8)¶
Re-enable interrupts only if
$were_onis 1, i.e. only if the matching@irq_disablefound them enabled.
Use them in a save/restore pair:
ram imut $were: u8 = @irq_disable()
# ... critical section ...
@irq_restore($were)