Skip to main content

Module scheduler

Module scheduler 

Source
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§

CpuUsageSnapshot
GlobalSchedState
Global task registry : cold path: fork, exit, all_tasks scan.
HeldLock 🔒
LockdepState 🔒
Per-CPU lockdep state, active only under cfg(debug_assertions).
PerCpuClassRqSet 🔒
SchedIdentity
Identity maps for the scheduler: PID/TID routing, process groups, session membership, and parent/child relationships.
SchedulerCpu 🔒
Per-CPU scheduler state
SchedulerMetricsSnapshot
SchedulerStateSnapshot
SwitchTarget 🔒
Information needed to perform a context switch after releasing the lock.

Enums§

LockRank 🔒
Lock ranks matching the total order documented in the module header.
SchedState
Formal scheduling state of a task, encoding ownership unambiguously.
WaitChildResult
Result of a non-blocking wait on child exit.

Constants§

STEAL_COOLDOWN_TICKS 🔒
STEAL_IMBALANCE_MIN 🔒

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 in maybe_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_IDENTITY read 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 parent by POSIX pid.
get_child_task_id_by_tid
Resolve a direct child of parent by 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 if cpu_index is the current CPU (the caller already handles the local-CPU case via yield_cpu).
set_process_group
Set process group id for target_pid (or current if None).
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).