Skip to content

Scheduling

Who decides what runs next, when, and on which core — the operating system's scheduler, or a runtime's event loop and executor.

All categories · How they connect

  • Scheduler — The part of an operating system or runtime that decides which ready thread or task runs next, on which core, and for how long.
  • Event loop — A loop on one thread that waits for events — a socket ready, a timer due, work finished — and runs the callbacks or resumes the tasks waiting on each.
  • Async runtime (executor and reactor) — The library that drives async tasks: an executor that polls the tasks that can make progress, and a reactor that wakes them when the I/O they wait for is ready.
  • I/O multiplexing — Asking the operating system to watch many sockets or file descriptors at once and report which are ready, so that one thread can serve thousands of connections.
  • Polling — Asking repeatedly whether something is ready instead of being told; in Rust, an executor polls a future and the future answers Ready or Pending.
  • Suspension point — A place where a coroutine or async function can pause and hand control back — an await, a yield — and where other tasks may run before it resumes.
  • Busy waiting — Waiting for a condition by checking it in a loop, burning CPU the whole time; worth it for a few nanoseconds inside a spinlock, wasteful for anything longer.
  • Scheduling policy — The rule a scheduler follows to pick what runs next: whether a running task can be interrupted, how priorities are set, and where idle cores find work.
    • Preemptive scheduling — The scheduler may stop a running thread at any moment, usually on a timer interrupt, and run another — no thread can hog the CPU, and any step can be interrupted.
    • Cooperative scheduling — A task runs until it gives way — at an await, a yield or a blocking call — so switches happen only at known points, and one task that never gives way stalls all the others.
    • Work stealing — Each worker thread keeps its own queue of tasks, and an idle worker takes tasks from a busy worker's queue, balancing the load without one central queue.

Inside this category

flowchart LR
  n_async_runtime["Async runtime (executor and reactor)"]
  n_cooperative_scheduling["Cooperative scheduling"]
  n_event_loop["Event loop"]
  n_io_multiplexing["I/O multiplexing"]
  n_polling["Polling"]
  n_preemptive_scheduling["Preemptive scheduling"]
  n_scheduler["Scheduler"]
  n_scheduling_policy["Scheduling policy"]
  n_suspension_point["Suspension point"]
  n_work_stealing["Work stealing"]
  n_async_runtime -->|uses| n_event_loop
  n_async_runtime -->|uses| n_io_multiplexing
  n_async_runtime -->|uses| n_polling
  n_async_runtime -->|uses| n_work_stealing
  n_cooperative_scheduling ---|vs| n_preemptive_scheduling
  n_cooperative_scheduling -->|is a| n_scheduling_policy
  n_cooperative_scheduling -->|uses| n_suspension_point
  n_event_loop -->|uses| n_io_multiplexing
  n_preemptive_scheduling -->|is a| n_scheduling_policy
  n_scheduler -->|uses| n_scheduling_policy
  n_work_stealing -->|is a| n_scheduling_policy