Scheduling
This document describes the scheduling implementation in the Kyronix kernel. It is the child of Kernel Implementation Notes.
The Kyronix kernel uses a per-CPU round-robin scheduler with lock-free bitmap-based ready-queue selection and hardware-assisted FPU context switching.
Scheduling Algorithm
Ready Queue and Bitmap
- Each CPU maintains a 64-bit ready bitmask (
g_ready_mask) representing the priority levels with at least one runnable thread. - Next-thread selection uses
__builtin_ctzll(Count Trailing Zeros, Long Long) ong_ready_maskto locate the lowest-numbered set bit in O(1) time. - Each priority level maps to a linked list of threads in the READY state.
Lock-Free Claim
sched_claim_nexttransitions a thread from READY to RUNNING using a Compare-And-Swap (CAS) operation, eliminating lock contention on the common path.- The CAS atomically marks the thread as RUNNING before any scheduler state is visible to other processors.
Round-Robin Fairness
- Per-CPU arrays (
g_last_scheduled) track the last scheduled thread per priority level to enforce round-robin fairness across threads of equal priority.
Context Switch
The context switch performs the following operations in sequence:
- Save callee-saved general-purpose registers from the outgoing thread.
- Execute
fxsave64to save the floating-point / SIMD state of the outgoing thread. - Restore callee-saved general-purpose registers for the incoming thread.
- Execute
fxrstor64to restore the floating-point / SIMD state of the incoming thread. - Write the FS base MSR (Model-Specific Register) for the incoming thread’s Thread-Local Storage (TLS).
- Load CR3 (Control Register 3) to switch to the incoming thread’s address space.
Preemption
- Preemption is triggered on Programmable Interval Timer (PIT) IRQ 0 and Local APIC timer interrupt (vector 224).
- The timer interrupt handler invokes the scheduler to perform a context switch if a higher-priority or equal-priority thread is runnable.
Application Processor Idle Loop
Application Processors (APs) execute the following idle loop:
- Call
sched_claim_nextto attempt to acquire a runnable thread. - If a thread is claimed, call
sched_switchto context-switch into it. - If no thread is available, execute
hlt(Halt) until the next interrupt.
Process States and Transitions
Threads transition through the following states:
UNUSED -> READY -> RUNNING -> READY
|-> WAITING
|-> ZOMBIE -> DYING
|-> STOPPED
UNUSED— Thread slot is unallocated.READY— Thread is runnable and waiting for CPU time.RUNNING— Thread is executing on a CPU.WAITING— Thread is blocked on an event (e.g., I/O, sleep).ZOMBIE— Thread has exited but its resources have not yet been reclaimed.DYING— Thread is in the final stage of resource teardown.STOPPED— Thread has been stopped (e.g., via signal).
Deferred Reaping
proc_defer_thread_reapstores a zombie thread in a pending list for deferred cleanup.- The next call to
proc_reap_pendingprocesses the deferred list and reclaims thread resources. - Deferred reaping avoids performing memory deallocation in the interrupt context where the thread transitions to ZOMBIE.
Last reviewed: 2026-07-22