Process scheduler

On this page 7

A process scheduler is the kernel component that decides which runnable process or thread runs on each CPU core, at what moment and for how long. Among the OS fundamentals, it is the mechanism that turns a few processor cores into the illusion that dozens or thousands of programs run at the same time, which is the basis of multitasking.

The scheduler balances goals that conflict: responsiveness for interactive programs, throughput for background work, fairness between users and processes, and predictable latency for time-critical tasks. Every general-purpose operating system, including Windows, macOS and Linux, makes these trade-offs differently, and each one exposes priorities and policies that administrators and developers can adjust.

How the process scheduler works

The scheduler manages threads in a small set of states: running on a core, ready and waiting for a core, or blocked while waiting for an event such as disk input, a network packet or a lock. Only ready threads compete for the processor. When a running thread blocks, finishes or uses up its time, the scheduler selects the next one and the kernel performs a context switch, saving one thread’s registers and loading another’s.

Modern kernels use preemptive scheduling. A timer interrupt or the arrival of a higher-priority thread lets the kernel take the processor away from the current thread, even if that thread does not cooperate. Each thread typically receives a time slice or quantum, commonly in the range of a few milliseconds to tens of milliseconds, depending on the system, the load and the scheduling policy.

The following table shows the main decisions the scheduler makes and what drives them.

DecisionMain inputsEffect on the system
Which thread runs nextPriority, waiting time, policyResponsiveness and fairness
How long it may runTime slice, load, priorityLatency versus switching overhead
Which core it usesCache affinity, core type, loadCache efficiency and power use
When to preemptTimer, wake-ups of urgent threadsReaction time to events
When to migrateImbalance between core queuesEven use of all cores
Core decisions of a process scheduler

Scheduling algorithms and policies

Textbook scheduling algorithms illustrate the basic trade-offs, and real schedulers combine elements of several of them. No single algorithm is optimal for every workload; each favors certain metrics such as average waiting time, fairness or worst-case latency.

AlgorithmPrincipleStrengthWeakness
First come, first servedRun in order of arrivalSimple, no starvationShort jobs wait behind long ones
Shortest job firstRun the shortest task nextLow average waiting timeNeeds run-time estimates
Round robinFixed time slice in rotationFair and responsiveOverhead with very short slices
Priority schedulingHighest priority runs firstSupports urgent workRisk of starvation
Multilevel feedback queuePriority adapts to behaviorFavors interactive tasksComplex tuning
Fair-share schedulingCPU time divided by weightsProportional fairnessLess suited to strict deadlines
Classic scheduling algorithms

Operating systems also offer real-time policies that bypass fairness: a real-time thread with a fixed priority runs as long as it is ready, ahead of all normal threads. This is useful for audio processing or control loops, but a faulty real-time thread can freeze the rest of the system, so these policies usually require elevated privileges.

Schedulers in current operating systems

Each major operating system implements its own design. Linux long used the Completely Fair Scheduler, which tracks virtual run time to share the CPU in proportion to weights, and newer kernels adopted the EEVDF scheduler, which adds deadline-based selection to improve latency. Windows uses a priority-based preemptive scheduler with 32 priority levels and temporary priority boosts for threads that wake up after input. macOS combines priority bands with quality-of-service classes that apps assign to their work.

Operating systemBasic modelUser-facing controls
LinuxFair scheduling with weights, plus real-time classesnice values from -20 to 19, scheduling policies
WindowsPriority levels 0-31 with dynamic boostsPriority classes in Task Manager
macOSPriority bands with quality-of-service classesQoS classes set by applications
How major operating systems approach scheduling

Processors with hybrid architectures, which combine performance cores and efficiency cores, add another dimension. The scheduler must decide which kind of core suits each thread, often with hints from the hardware about the thread’s behavior, and a wrong placement can make a foreground task noticeably slower.

The scheduler works closely with other kernel subsystems, and problems blamed on it often originate elsewhere. It decides who uses the CPU, while memory management decides who uses RAM and the I/O scheduler decides the order of storage requests.

MechanismWhat it controlsRelationship to the scheduler
Context switchSaving and restoring thread stateThe action the scheduler triggers
Interrupt handlingReaction to hardware eventsOften wakes threads and causes rescheduling
Memory managementAllocation of physical memoryHeavy paging leaves threads blocked
I/O schedulerOrder of disk requestsSeparate queue, separate policy
Inter-process communicationData exchange between processesWaiting on messages blocks threads
Neighboring mechanisms and how they differ

Common problems and tuning pitfalls

Most scheduling problems show up as stutter, lag or uneven throughput rather than outright failures. Understanding the typical causes avoids tuning the wrong parameter.

  • Starvation: low-priority threads may never run under strict priority rules; aging or fair-share policies prevent it.
  • Priority inversion: a high-priority thread waits for a lock held by a low-priority one; priority inheritance solves this.
  • Too many runnable threads: excessive threads raise context-switch overhead and cache misses without adding throughput.
  • Misused real-time priority: assigning real-time priority to ordinary programs can block system services and input handling.
  • Blaming the CPU: high load averages often reflect threads blocked on storage, not a lack of processor time.

In practice, the default policies are well tuned for most desktop and server workloads. Adjusting priorities helps in targeted cases, such as lowering a backup job’s priority, but broad manual tuning rarely improves results.

In everyday language

Imagine one chef cooking for many tables. The chef works on one dish for a moment, then switches to another. The diners feel as if every meal is being cooked at once. The process scheduler is the kitchen manager who decides which dish the chef handles next.

Urgent orders, like a waiting customer at the counter, get attention first. Slow dishes, like a stew, can simmer in the background. Good scheduling keeps everyone served without letting anyone wait forever.

Seen in the real world

A video editor works on a laptop with eight cores while a large export runs in the background. During the export, scrolling the timeline becomes jerky because the export threads compete for every core. The editor lowers the export’s priority, which on Linux means raising its nice value to 10, and leaves the editing application at normal priority.

The scheduler now gives interactive threads precedence whenever they wake up, and the export uses the remaining processor time. The timeline scrolls smoothly again, while the export takes only slightly longer, because idle CPU cycles are still fully used by the background job.