Expand description
Scheduler implementation
Implements a per-CPU, multi-class, SMP scheduler for Strat9-OS with support for cooperative and preemptive multitasking.
§Scheduler locking contract — mandatory total order
GLOBAL_SCHED_STATE (rank 1)
-> SCHED_IDENTITY write (rank 2)
-> BLOCKED_TASKS (rank 3)
-> LOCAL_SCHEDULERS[cpu] (rank 4)
-> Task/Process internal lock (rank 5)SCHED_IDENTITY read is observational only:
- do not acquire any scheduler lock while holding it;
- copy the result, release it, then begin a mutating operation.
§Forbidden
- Acquiring GLOBAL, IDENTITY, BLOCKED, or another LOCAL while holding LOCAL.
- Holding two LOCAL locks simultaneously.
- Allocating, logging, VFS access, IPI sends, or context switching while any scheduler spinlock is held.
- Any transition from Blocked directly to Running (must go through Runnable).
§Cross-CPU operations
Use a two-phase protocol: detach under the source local lock, release it, then attach under the destination local lock.
§Task ownership invariant
A non-idle task is in exactly one scheduling ownership state: New, Runnable(cpu), Running(cpu), Blocked, Zombie, or Reaped.
§Canonical state machine
New -> Runnable(cpu)
Runnable(cpu) -> Running(cpu) [selection / preempt]
Running(cpu) -> Runnable(cpu) [tick / yield / preempt]
Running(cpu) -> Blocked [block_current]
Blocked -> Runnable(cpu) [wake_task]
Running/Runnable/Blocked -> Zombie [exit / kill]
Zombie -> Reaped [waitpid / reap]Each transition has a single owner (the function performing it) and a
defined transaction: which locks are taken, which containers lose the task,
which containers receive it, and when taskcpu becomes visible.
§Metrics
All counters (FORCE_RESCHED_HINT, RESCHED_IPI_PENDING, ticks, etc.) are lock-free atomics and must never be used to drive state transitions.
Re-exports§
pub use deferred_work::has_pending;pub use deferred_work::metrics_snapshot as deferred_work_metrics;pub use deferred_work::process_deferred_work;pub use deferred_work::raise_deferred_work;pub use deferred_work::raise_tick_deferred_work;pub use deferred_work::reset_metrics as reset_deferred_work_metrics;pub use deferred_work::DeferredWork;pub use deferred_work::DeferredWorkMetrics;
Modules§
- core_
impl 🔒 - deferred_
work - Deferred work queue — softirq-equivalent for Strat9-OS.
- perf_
counters - Lightweight TSC-based performance counters for critical kernel paths.
- runtime_
ops 🔒 - task_
ops 🔒 - timer_
ops 🔒
Structs§
- CpuUsage
Snapshot - Global
Sched State - Global task registry : cold path: fork, exit, all_tasks scan.
- Held
Lock 🔒 - Lockdep
State 🔒 - Per-CPU lockdep state, active only under
cfg(debug_assertions). - PerCpu
Class 🔒RqSet - Sched
Identity - Identity maps for the scheduler: PID/TID routing, process groups, session membership, and parent/child relationships.
- Scheduler
Cpu 🔒 - Per-CPU scheduler state
- Scheduler
Metrics Snapshot - Scheduler
State Snapshot - Switch
Target 🔒 - Information needed to perform a context switch after releasing the lock.
Enums§
- Lock
Rank 🔒 - Lock ranks matching the total order documented in the module header.
- Sched
State - Formal scheduling state of a task, encoding ownership unambiguously.
- Wait
Child Result - Result of a non-blocking wait on child exit.
Constants§
Statics§
- BLOCKED_
TASKS 🔒 - Blocked tasks registry — rank 3 in the total lock order.
- CPU_
FAIR_ 🔒RUNTIME_ TICKS - CPU_
IDLE_ 🔒TICKS - CPU_
PREEMPT_ 🔒COUNT - CPU_
RT_ 🔒RUNTIME_ TICKS - CPU_
STEAL_ 🔒IN_ COUNT - CPU_
STEAL_ 🔒OUT_ COUNT - CPU_
SWITCH_ 🔒COUNT - CPU_
TOTAL_ 🔒TICKS - Per-CPU scheduler tick counters used for CPU usage estimation.
- CPU_
TRY_ 🔒LOCK_ FAIL_ COUNT - FIRST_
PREEMPT_ 🔒LOGGED - One-shot flag per CPU: set to true after the first preemption is logged. Prevents flooding the serial port with a preempt trace on every tick.
- FORCE_
RESCHED_ 🔒HINT - Lock-free per-CPU hint: request a local preemption as soon as maybe_preempt
can observe scheduler state. Written from IRQ paths without touching
GLOBAL_SCHED_STATE, consumed under scheduler lock inmaybe_preempt. - GLOBAL_
SCHED_ 🔒STATE - Global scheduler state — rank 1 (root) in the total lock order.
- IPI_
SEND_ 🔒TRACE_ BUDGET - LAST_
STEAL_ 🔒TICK - LOCAL_
SCHEDULERS 🔒 - Per-CPU local scheduler locks — rank 4 in the total lock order.
- LOCKDEP 🔒
- Per-CPU lockdep state. Each CPU tracks its own stack of held scheduler locks. SAFETY: accessed only from the owning CPU with IRQs disabled (no concurrent access).
- RESCHED_
IPI_ 🔒PENDING - SCHED_
IDENTITY 🔒 - Identity maps — rank 2 (write) / 2R (read) in the total lock order.
- SCHED_
VERBOSE 🔒 - Verbose scheduler trace switch.
- TICK_
COUNT 🔒 - Global tick counter (safe to increment from interrupt context)
Functions§
- active_
cpu_ 🔒count - Performs the active cpu count operation.
- add_
task - Add a task to the scheduler
- add_
task_ with_ parent - Add a task and register a parent/child relation.
- assert_
no_ 🔒identity_ read_ held - Check that
SCHED_IDENTITYread is not held (observational-only contract). - block_
current_ task - Block the current task and yield to the scheduler.
- class_
table - Return the scheduler class-table currently in use.
- clear_
task_ wake_ deadline - Performs the clear task wake deadline operation.
- configure_
class_ table - Configure scheduler class pick/steal order at runtime.
- cpu_
is_ 🔒valid - Performs the cpu is valid operation.
- cpu_
usage_ snapshot - Performs the cpu usage snapshot operation.
- create_
session - Create a new session for the calling task.
- current_
cpu_ 🔒index - Performs the current cpu index operation.
- current_
pgid - Get the current process group id.
- current_
pid - Get the current process ID (POSIX pid).
- current_
sid - Get the current session id.
- current_
task_ clone - Get the current task (cloned Arc), if any.
- current_
task_ clone_ spin_ debug - Debug-only blocking variant used to diagnose early ring3 entry stalls.
- current_
task_ clone_ try - Best-effort, non-blocking variant of
current_task_clone. - current_
task_ id - Get the current task’s ID (if any task is running).
- current_
task_ id_ try - Get the current task’s ID without blocking (safe for exceptions).
- current_
tid - Get the current thread ID (POSIX tid).
- debug_
scheduler_ lock_ addr - Returns the scheduler lock address for deadlock tracing.
- exit_
current_ task - Mark the current task as Dead and yield to the scheduler.
- finish_
interrupt_ switch - Finalize a preemption-driven switch once the raw timer stub has already moved onto the next task’s kernel stack.
- finish_
switch - Called immediately after a context switch completes (in the new task’s context). This safely re-queues the previously running task now that its state is fully saved.
- flush_
deferred_ silo_ cleanups - get_
all_ tasks - Get a list of all tasks in the system (for timer checking). Returns None if scheduler is not initialized or currently locked.
- get_
child_ task_ id_ by_ pid - Resolve a direct child of
parentby POSIX pid. - get_
child_ task_ id_ by_ tid - Resolve a direct child of
parentby POSIX tid. - get_
parent_ id - Get parent task ID for a child task.
- get_
parent_ pid - Get parent process ID for a child task.
- get_
pgid_ by_ pid - Resolve a PID to the current process group id.
- get_
sid_ by_ pid - Resolve a PID to the current session id.
- get_
task_ by_ id - Get a task by its TaskId (if still registered).
- get_
task_ by_ pid - Resolve a POSIX pid to the corresponding task.
- get_
task_ id_ by_ pid - Resolve a POSIX pid to internal TaskId.
- get_
task_ id_ by_ tid - Resolve a POSIX tid to the corresponding internal task id.
- get_
task_ ids_ in_ pgid - Collect task IDs that currently belong to process group
pgid. - get_
task_ ids_ in_ tgid - Collect task IDs that currently belong to thread group
tgid. - init_
scheduler - Initialize the scheduler
- kill_
task - Kill a task by ID (best-effort).
- lockdep_
acquire 🔒 - Record a lock acquisition in the per-CPU lockdep state.
- lockdep_
assert_ 🔒held - Assert that a specific rank is currently held on this CPU.
- lockdep_
assert_ 🔒no_ locks - Assert that no scheduler locks are held on this CPU.
- lockdep_
release 🔒 - Record a lock release in the per-CPU lockdep state.
- log_
state - Dump per-cpu scheduler queues for tracing/debug.
- maybe_
preempt - Called from the timer interrupt handler (or a resched IPI) to potentially preempt the current task.
- maybe_
preempt_ from_ interrupt - Interrupt-aware preemption path.
- note_
try_ lock_ fail - Performs the note try lock fail operation.
- note_
try_ 🔒lock_ fail_ on_ cpu - Performs the note try lock fail on cpu operation.
- request_
force_ 🔒resched_ hint - Request a local force-reschedule hint for
cpu. - reset_
scheduler_ metrics - Performs the reset scheduler metrics operation.
- resume_
task - Resume a previously suspended task by ID.
- sched_
trace 🔒 - Performs the sched trace operation.
- schedule
- Start the scheduler (called from kernel_main)
- schedule_
on_ cpu - Performs the schedule on cpu operation.
- scheduler_
metrics_ snapshot - Performs the scheduler metrics snapshot operation.
- send_
resched_ 🔒ipi_ to_ cpu - Send a reschedule IPI to
cpu_index. No-op if APIC is not initialized, or ifcpu_indexis the current CPU (the caller already handles the local-CPU case viayield_cpu). - set_
process_ group - Set process group id for
target_pid(or current ifNone). - set_
task_ sched_ policy - Update a task scheduling policy and requeue if needed.
- set_
task_ wake_ deadline - Sets task wake deadline.
- set_
verbose - Enable or disable verbose scheduler tracing.
- state_
snapshot - Structured scheduler state snapshot for shell/top/debug tooling.
- suspend_
task - Suspend a task by ID (best-effort).
- take_
force_ 🔒resched_ hint - Consume and clear the local force-reschedule hint for
cpu. - ticks
- Get the current tick count
- timer_
tick - Timer interrupt handler - called from interrupt context.
- try_
wait_ child - Try to reap a zombie child.
- validate_
scheduler_ 🔒invariants - Validate scheduler-wide invariants in debug builds.
- validate_
task_ 🔒context - Performs the validate task context operation.
- verbose_
enabled - Return current verbose tracing state.
- wake_
task - Wake a blocked task by its ID.
- yield_
dead_ task - Force a context switch away from the current task, unconditionally.
- yield_
task - Yield the current task to allow other tasks to run (cooperative).