Scheduler Implementations

Relevant source files

This document provides an overview of the three scheduler algorithm implementations provided by the crate: FIFO, Round Robin, and Completely Fair Scheduler (CFS). Each implementation adheres to the unified BaseScheduler interface while providing distinct scheduling behaviors and performance characteristics.

For details about the BaseScheduler trait and core architecture, see Core Architecture. For detailed documentation of each individual scheduler, see FIFO Scheduler, Completely Fair Scheduler (CFS), and Round Robin Scheduler.

Scheduler Overview

The crate provides three distinct scheduling algorithms, each designed for different use cases and performance requirements:

SchedulerTypePriority SupportPreemptionData StructureUse Case
FifoSchedulerCooperativeNoNolinked_list_r4l::ListSimple sequential execution
RRSchedulerPreemptiveNoTime-basedVecDequeFair time sharing
CFSchedulerPreemptiveYes (nice values)Virtual runtimeBTreeMapAdvanced fair scheduling

Each scheduler manages tasks wrapped in scheduler-specific container types that add necessary scheduling metadata.

Sources: src/lib.rs(L1 - L8)  src/fifo.rs(L14 - L22)  src/round_robin.rs(L46 - L56)  src/cfs.rs(L100 - L102) 

Implementation Architecture

Trait Implementation Hierarchy

flowchart TD
subgraph subGraph3["CFS Implementation"]
    CFS["CFScheduler<T>"]
    CFT["Arc<CFSTask<T>>"]
    CFS_queue["ready_queue: BTreeMap"]
    CFS_vtime["vruntime tracking"]
    CFS_nice["nice values"]
end
subgraph subGraph2["Round Robin Implementation"]
    RRS["RRScheduler<T, MAX_TIME_SLICE>"]
    RRT["Arc<RRTask<T, S>>"]
    RRS_queue["ready_queue: VecDeque"]
    RRS_slice["time_slice: AtomicIsize"]
end
subgraph subGraph1["FIFO Implementation"]
    FS["FifoScheduler<T>"]
    FT["Arc<FifoTask<T>>"]
    FS_queue["ready_queue: List"]
end
subgraph subGraph0["BaseScheduler Trait"]
    BS["BaseScheduler<SchedItem>"]
    BS_init["init()"]
    BS_add["add_task(task)"]
    BS_remove["remove_task(task)"]
    BS_pick["pick_next_task()"]
    BS_put["put_prev_task(prev, preempt)"]
    BS_tick["task_tick(current)"]
    BS_prio["set_priority(task, prio)"]
end

BS --> CFS
BS --> FS
BS --> RRS
CFS --> CFS_nice
CFS --> CFS_queue
CFS --> CFS_vtime
CFS --> CFT
FS --> FS_queue
FS --> FT
RRS --> RRS_queue
RRS --> RRS_slice
RRS --> RRT

Sources: src/lib.rs(L24 - L68)  src/fifo.rs(L23 - L38)  src/round_robin.rs(L58 - L73)  src/cfs.rs(L103 - L122) 

Task Wrapper Architecture

flowchart TD
subgraph subGraph2["Scheduling Metadata"]
    LinkedList["linked_list_r4l node"]
    TimeSlice["time_slice: AtomicIsize"]
    VRuntime["init_vruntime: AtomicIsize"]
    Delta["delta: AtomicIsize"]
    Nice["nice: AtomicIsize"]
    TaskId["id: AtomicIsize"]
end
subgraph subGraph1["Inner Task"]
    T["T (user task)"]
end
subgraph subGraph0["Task Wrappers"]
    FifoTask["FifoTask<T>"]
    RRTask["RRTask<T, MAX_TIME_SLICE>"]
    CFSTask["CFSTask<T>"]
end

CFSTask --> Delta
CFSTask --> Nice
CFSTask --> T
CFSTask --> TaskId
CFSTask --> VRuntime
FifoTask --> LinkedList
FifoTask --> T
RRTask --> T
RRTask --> TimeSlice

Sources: src/fifo.rs(L7 - L12)  src/round_robin.rs(L7 - L13)  src/cfs.rs(L7 - L14) 

Scheduling Behavior Comparison

Core Scheduling Methods

Each scheduler implements the BaseScheduler methods differently:

Task Selection (pick_next_task):

Task Insertion (put_prev_task):

Preemption Logic (task_tick):

Sources: src/fifo.rs(L40 - L68)  src/round_robin.rs(L75 - L113)  src/cfs.rs(L124 - L193) 

Priority Support

Only the CFScheduler supports dynamic priority adjustment through nice values:

flowchart TD
subgraph subGraph0["CFS Priority Implementation"]
    CFSWeight["get_weight() from nice value"]
    CFSVruntime["adjust virtual runtime calculation"]
    CFSNICES["NICE2WEIGHT_POS/NEG arrays"]
end
SetPrio["set_priority(task, prio)"]
FifoCheck["FifoScheduler?"]
RRCheck["RRScheduler?"]
CFSCheck["CFScheduler?"]
FifoReturn["return false"]
RRReturn["return false"]
CFSRange["prio in [-20, 19]?"]
CFSSet["task.set_priority(prio)"]
CFSFalse["return false"]
CFSTrue["return true"]

CFSCheck --> CFSRange
CFSRange --> CFSFalse
CFSRange --> CFSSet
CFSSet --> CFSTrue
CFSSet --> CFSWeight
CFSWeight --> CFSNICES
CFSWeight --> CFSVruntime
FifoCheck --> FifoReturn
RRCheck --> RRReturn
SetPrio --> CFSCheck
SetPrio --> FifoCheck
SetPrio --> RRCheck

Sources: src/fifo.rs(L65 - L67)  src/round_robin.rs(L110 - L112)  src/cfs.rs(L185 - L192)  src/cfs.rs(L23 - L29)  src/cfs.rs(L43 - L50) 

Data Structure Performance Characteristics

OperationFifoSchedulerRRSchedulerCFScheduler
add_taskO(1)O(1)O(log n)
pick_next_taskO(1)O(1)O(log n)
remove_taskO(1)O(n)O(log n)
put_prev_taskO(1)O(1)O(log n)
Memory overheadMinimalLowModerate

The choice of data structure reflects each scheduler's priorities:

  • FifoScheduler uses linked_list_r4l::List for optimal insertion/removal performance
  • RRScheduler uses VecDeque for simple front/back operations but suffers from O(n) arbitrary removal
  • CFScheduler uses BTreeMap keyed by (vruntime, task_id) to maintain virtual runtime ordering

Sources: src/fifo.rs(L23 - L25)  src/round_robin.rs(L58 - L60)  src/cfs.rs(L103 - L107) 

Thread Safety and Atomic Operations

All task metadata requiring atomic access is implemented using AtomicIsize:

This design enables safe concurrent access to task state during scheduling operations without requiring additional synchronization primitives.

Sources: src/round_robin.rs(L10 - L13)  src/cfs.rs(L8 - L14)  src/fifo.rs(L7 - L12)