Jump to content

Multitasking functionality

From Wikibooks, open books for an open world


multitasking
execution
threads or tasks
synchronization
Scheduler
interrupts core
CPU specific

Linux kernel is a preemptive multitasking operating system. As a multitasking OS, it allows multiple processes to share processors (CPUs) and other system resources. Each CPU executes a single task at a time. However, multitasking allows each processor to switch between tasks that are being executed without having to wait for each task to finish. For that, the kernel can, at any time, temporarily interrupt a task being carried out by the processor, and replace it by another task that can be new or a previously suspended one. The operation involving the swapping of the running task is called context switch.

Execution

[edit | edit source]

โšฒ API โ†ช โš™๏ธ implementations

man 2 execve โ†ช do_execveat_common id runs an executable file in the context of current process, replacing the previous executable. This system call is used by family of functions of libc man 3 exec. The ELF binary format is loaded by fs/binfmt_elf.c src.

man 2 clone. Clone creates a child process that may share parts of its execution context with the parent. It is often used to implement threads (though programmers will typically use a higher-level interface such as man 7 pthreads, implemented on top of clone).

man 2 wait โ†ช kernel_waitid id suspends the execution of the calling process until one of its child processes terminates.

Syscall man 2 getpid โ†ช task_tgid_vnr id returns PID of the current process which internally is called TGID - thread group id. A process can contain many threads. man 2 gettid โ†ช task_pid_vnr id returns thread id. Which internally is historically called PID. โš ๏ธ Warning: confusion. User space PID โ‰  kernel space PID. man 1 ps -AF lists current processes and thread as LWP. For a single thread process all these IDs are equal.

High-resolution delays:

man 2 nanosleep โ†ช sys_nanosleep id
hrtimer_nanosleep id
man 2 clock_nanosleep โ†ช sys_clock_nanosleep id

Wait for a signal:

man 2 pause โ†ช sys_pause id
man 2 sigsuspend โ†ช sys_sigsuspend id

๐Ÿ”จ stress-ng --context, --switch

See Processes for process creation and termination.

Inter-process communication

[edit | edit source]

Inter-process communication (IPC) refers specifically to the mechanisms an operating system provides to allow processes it manages to share data. Methods for achieving IPC are divided into categories which vary based on software requirements, such as performance and modularity requirements, and system circumstances. Linux inherited from Unix the following IPC mechanisms:

Signals (โšฒ API โ†ช โš™๏ธ implementations):

man 2 kill sends signal to a process
man 2 tgkill โ†ช do_tkill id sends a signal to a thread
man 2 process_vm_readv โ†ช process_vm_rw id - zero-copy data transfer between process address spaces
man 2 sigaction โ†ช do_sigaction id – examine and change a signal action
man 2 sigprocmask – examine and change blocked signals
man 2 sigpending โ†ช do_sigpending id – examine pending signals
man 2 sigsuspend – wait for a signal
man 2 sigaltstack – set or get signal stack context
man 2 sigtimedwait โ†ช do_sigtimedwait id – synchronously wait for queued signals
man 7 signal – overview of signals
linux/sched/signal.h inc – signal-related task accessors
kernel/signal.c src – signal delivery and handling
๐Ÿ”จ stress-ng --sigq


Anonymous pipes and named pipes (FIFOs) man 2 mknod โ†ช do_mknodat id S_IFIFO id
Express Data Path PF_XDP id
Unix domain socket PF_UNIX id
Memory-mapped files man 2 mmap โค‘ ksys_mmap_pgoff id
man 2 eventfd โ†ช do_eventfd id – event notification via file descriptor
man 2 signalfd โ†ช do_signalfd4 id – receive signals via file descriptor
man 2 timerfd_create – timer notification via file descriptor
Sys V IPC:
Message queues: man 2 msgget, man 2 msgsnd, man 2 msgrcv โ†ช ipc/msg.c src
Semaphores
Shared memory: man 2 shmget, man 2 shmctl, man 2 shmat, man 2 shmdt โ†ช ipc/shm.c src
POSIX message queues:
man 7 mq_overview, man 3 mq_open, man 3 mq_send, man 3 mq_receive โ†ช ipc/mqueue.c src ๐Ÿ”จ --mq


๐Ÿ“– References

Inter-process communication
man 7 sysvipc

Threads or tasks

[edit | edit source]

In Linux kernel "thread" and "task" are almost synonyms.

โšฒ API

linux/sched.h inc - the main scheduler API
task_struct id
arch/x86/include/asm/current.h src – x86 current task pointer
current id and get_current id () return current task_struct id
uapi/linux/taskstats.h inc per-task statistics
linux/thread_info.h inc
current_thread_info id() returns thread_info id
linux/sched/task.h inc - interface between the scheduler and various task lifetime (fork()/exit()) functionality
linux/kthread.h inc - simple interface for creating and stopping kernel threads without mess.
kthread_run id creates and wakes a thread
kthread_create id


โš™๏ธ Internals

kthread_run id โ†ฏ hierarchy:
kernel/kthread.c src – kernel thread creation and management
kthreadd id – parent kernel thread and the creator of all other kernel threads.

Dequeues kthread_create_info id from kthread_create_list id.

create_kthread id
kernel_thread id
kthread id – invokes threadfn id
__kthread_create_on_node id – enqueues kthread_create_info id into kthread_create_list id
kernel/fork.c src – process creation and cloning
kernel_thread id
kernel_clone id

๐Ÿ”จ stress-ng --clone, --fork, --pthread

Scheduler

[edit | edit source]

The scheduler is the part of the operating system that decides which process runs at a certain point in time. It usually has the ability to pause a running process, move it to the back of the running queue and start a new process.

Active processes are placed in an array called a run queue, or runqueue - rq id. The run queue may contain priority values for each process, which will be used by the scheduler to determine which process to run next. To ensure each program has a fair share of resources, each one is run for some time period (quantum) before it is paused and placed back into the run queue. When a program is stopped to let another run, the program with the highest priority in the run queue is then allowed to execute. Processes are also removed from the run queue when they ask to sleep, are waiting on a resource to become available, or have been terminated.

Since version 6.6 the Linux kernel uses the Earliest eligible virtual deadline first scheduling (EEVDF) algorithm, which replaced the Completely Fair Scheduler (CFS). While much of the CFS infrastructure remains: sched_entity id, cfs_rq id, the red-black tree, load balancing, and kernel/sched/fair.c src — the task selection logic is fundamentally different. EEVDF is based on a classic scheduling algorithm originally designed for packet networks. The scheduler has a scheduling complexity of O(log N), where N is the number of tasks in the runqueue. Both picking and reinserting a task require O(log N) operations, because the run queue is implemented as a redโ€“black tree.

The runqueue (cfs_rq id) is implemented as a red-black tree representing a "timeline" of future task execution. The scheduler uses nanosecond granularity accounting and requires no heuristics or interactivity estimators.

EEVDF improves sleeper fairness over CFS by tracking lag (vlag id) — the difference between the service a task was entitled to and the service it actually received. When a sleeping task wakes up, its lag determines eligibility, ensuring interactive tasks get prompt service without starving long-running tasks.

The data structure used for the scheduling algorithm is a red-black tree in which the nodes are sched_entity id structures, embedded in task_struct id.

With EEVDF, each task has a time slice (sysctl_sched_base_slice id, default 0.7ms) that determines its request length. EEVDF computes a virtual deadline for each task: vd_i = ve_i + r_i/w_i, where ve_i is the eligible time, r_i is the request size, and w_i is the weight (determined by nice value). The scheduler picks the eligible task with the earliest virtual deadline via pick_eevdf id.

The Linux kernel contains different scheduler classes (or policies). The EEVDF scheduler handles SCHED_NORMAL id (aka SCHED_OTHER). The kernel also contains two additional classes SCHED_BATCH id and SCHED_IDLE id, and another two real-time scheduling classes named SCHED_FIFO id (realtime first-in-first-out) and SCHED_RR id (realtime round-robin), with a third realtime scheduling policy known as SCHED_DEADLINE id that implements the earliest deadline first algorithm (EDF) added later. Any realtime scheduler class takes precedence over any of the "normal" —i.e. non realtime— classes. The scheduler class is selected and configured through the man 2 sched_setscheduler โ†ช do_sched_setscheduler id system call.

Properly balancing latency, throughput, and fairness in schedulers is an open problem.[1]


โšฒ API

man 1 renice – priority of running processes
man 1 nice – run a program with modified scheduling priority
man 1 chrt – manipulate the real-time attributes of a process
man 2 sched_getattr โ†ช sys_sched_getattr id – get scheduling policy and attributes
linux/sched.h inc – the main scheduler API
schedule id
man 2 getpriority, man 2 setpriority
man 2 sched_setscheduler, man 2 sched_getscheduler
/sys/kernel/debug/sched/ – scheduler debugfs tuning directory
features – toggle scheduler feature flags
base_slice_ns – EEVDF base time slice (default 700000)
migration_cost_ns – cost threshold for task migration between CPUs
nr_migrate – max tasks to migrate per balancing pass
debug – dump detailed scheduler state
numa_balancing/ – NUMA balancing scan parameters


โš™๏ธ Internals

sched_init id is called from start_kernel id
__schedule id is the main scheduler function.
runqueues id, this_rq id
kernel/sched src – scheduler subsystem
kernel/sched/core.c src – core scheduling logic
kernel/sched/fair.c src implements SCHED_NORMAL id, SCHED_BATCH id, SCHED_IDLE id
pick_eevdf id – core of EEVDF
sched_setscheduler id, sched_getscheduler id
task_struct id::rt_priority id and other members with less unique identifiers

๐Ÿ”จ stress-ng --schedpolicy


๐Ÿ› ๏ธ Utilities

man 1 pidstat
man 1 pcp-pidstat
man 1 perf-sched
Understanding Scheduling Behavior with SchedViz


๐Ÿ“– References

man 7 sched
Scheduling doc
EEVDF Scheduler doc
An EEVDF CPU scheduler for Linux LWN
Delaying and scheduling routines doc
CFS
Completely Fair Scheduler doc
CFS Bandwidth Control doc
CPU cgroup controller
CPU cgroup interface files doc
Completely fair scheduler LWN
Tuning the task scheduler
stop using CPU limits on Kubernetes
Deadline Task Scheduler doc
sched ltp
sched_setparam ltp
sched_getscheduler ltp
sched_setscheduler ltp


๐Ÿ“š Further reading about the scheduler

Tuning scheduling policy, RHEL
Scheduler tracing
bcc/ebpf CPU and scheduler tools


Preemption

[edit | edit source]

Preemption refers to the ability of the system to interrupt a running task to switch to another task. This is essential for ensuring that high-priority tasks receive the necessary CPU time and for improving the system's responsiveness. In Linux, preemption models define how and when the kernel can preempt tasks. Different models offer varying trade-offs between system responsiveness and throughput.

๐Ÿ“– References

Proper Locking Under a Preemptible Kernel doc
preempt_enable id – decrement the preempt counter
preempt_disable id – increment the preempt counter
preempt_enable_no_resched id – decrement, but do not immediately preempt
preempt_check_resched id – if needed, reschedule
preempt_count id – return the preempt counter
kernel/Kconfig.preempt src – preemption model configuration
CONFIG_PREEMPT_NONE id – no forced preemption for servers
CONFIG_PREEMPT_VOLUNTARY id – voluntary preemption for desktops
CONFIG_PREEMPT id – preemptible except for critical sections for low-latency desktops
CONFIG_PREEMPT_RT id – real-time preemption for highly responsive applications
CONFIG_PREEMPT_DYNAMIC id – allows runtime switching of preemption model
/sys/kernel/debug/sched/preempt – shows and controls the active preemption model

sched_ext

[edit | edit source]

Since version 6.12 the kernel supports SCHED_EXT id — an extensible scheduler class whose behavior is defined by a set of eBPF programs. Any scheduling algorithm can be implemented on top of sched_ext, loaded and unloaded dynamically at runtime. The system integrity is maintained no matter what the BPF scheduler does: the default scheduling behavior is restored on error or when a runnable task stalls.


โš™๏ธ Internals

CONFIG_SCHED_CLASS_EXT id
kernel/sched/ext.c src – extensible BPF scheduler class
sched_ext_ops id – BPF scheduler operations
sched_ext_entity id – per-task sched_ext data, embedded in task_struct id


๐Ÿ‘ Examples

tools/sched_ext src – in-tree example BPF schedulers


๐Ÿ“– References

Extensible Scheduler Class doc
sched-ext/scx – production BPF schedulers
Scheduler BPF LWN

Energy Aware Scheduling

[edit | edit source]

๐Ÿš€ advanced topic

Since version 5.0, Energy Aware Scheduling (EAS) gives the scheduler the ability to predict the impact of its decisions on the energy consumed by CPUs. EAS relies on an Energy Model (EM) to select an energy efficient CPU for each task, with minimal impact on throughput. EAS operates only on heterogeneous CPU topologies (such as ARM big.LITTLE) where the potential for energy savings is highest.


โšฒ API

/proc/sys/kernel/sched_energy_aware – enable or disable EAS
linux/energy_model.h inc
em_perf_domain id – performance domain descriptor
em_cpu_get id – get the EM for a given CPU


โš™๏ธ Internals

CONFIG_ENERGY_MODEL id
find_energy_efficient_cpu id – find most energy-efficient target CPU for a waking task
kernel/power/energy_model.c src – CPU energy model framework


๐Ÿ“– References

Energy Aware Scheduling doc
Energy Model of devices doc

Wait queues

[edit | edit source]

A wait queue in the kernel is a data structure that allows one or more processes to wait (sleep) until something of interest happens. They are used throughout the kernel to wait for available memory, I/O completion, message arrival, and many other things. In the early days of Linux, a wait queue was a simple list of waiting processes, but various scalability problems (including the thundering herd problem) have led to the addition of a fair amount of complexity since then.


โšฒ API

linux/wait.h inc

wait_queue_head id consists of double linked list of wait_queue_entry id and a spinlock.

Waiting for simple events:

Use one of two methods for wait_queue_head id initialization:
init_waitqueue_head id initializes wait_queue_head id in function context
DECLARE_WAIT_QUEUE_HEAD id - actually defines wait_queue_head id in global context
Wait alternatives:
wait_event_interruptible id - preferable wait
wait_event_interruptible_timeout id
wait_event id - uninterruptible wait. Can cause deadlock โš 
wake_up id etc

๐Ÿ‘ For example usage see references to unique suspend_queue id.

Explicit use of add_wait_queue instead of simple wait_event for complex cases:

DECLARE_WAITQUEUE id actually defines wait_queue_entry with default_wake_function id
add_wait_queue id inserts process in the first position of a wait queue
remove_wait_queue id


โš™๏ธ Internals

___wait_event id
__add_wait_queue id
__wake_up_common id, try_to_wake_up id
kernel/sched/wait.c src – wait queue implementation

Simple wait queues – simplified version with raw spinlock, suitable for RT and restricted contexts:

linux/swait.h inc
swait_queue_head id, swait_queue id
kernel/sched/swait.c src – simple wait queue implementation


๐Ÿ“– References

Wait queues and Wake events doc


Real-time

[edit | edit source]

RT preemption

[edit | edit source]

The Linux Foundation's Real-Time Linux (RTL) collaborative project is focused on improving the real-time capabilities of Linux and advancing the adoption of real-time Linux in various industries, including aerospace, automotive, robotics, and telecommunications.

Parameter CONFIG_PREEMPT_RT id enables real-time preemption.

RT scheduling policies

[edit | edit source]

Scheduling policies for RT:

SCHED_FIFO id, SCHED_RR id
implemented in kernel/sched/rt.c src
SCHED_DEADLINE
implemented in kernel/sched/deadline.c src


API:

man 1 chrt – manipulate the real-time attributes of a process
man 2 sched_rr_get_interval – get the SCHED_RR interval for the named process
man 2 sched_setscheduler, sched_getscheduler – set and get scheduling policy/parameters
man 2 sched_get_priority_min, sched_get_priority_max – get static priority range

RT scheduler tunables:

/proc/sys/kernel/sched_rt_period_us – period over which RT task bandwidth is measured (default 1000000 ยตs = 1 s)
/proc/sys/kernel/sched_rt_runtime_us – maximum time RT tasks may consume per period (default 950000 ยตs); set to -1 to disable the RT bandwidth limit
/sys/kernel/realtime – indicates the running kernel has PREEMPT_RT enabled (present only on RT kernels)
/sys/devices/system/clocksource/clocksource0/current_clocksource – active clocksource, critical for RT timing accuracy

๐Ÿ› ๏ธ Utilities

tuna – view and change thread attributes (affinity, scheduling policy, priority)
RHEL tuna guide
sos kernelrt plugin – diagnostics collection for RT kernel

Priority inversion occurs when a high-priority task blocks on a resource held by a low-priority task, while a medium-priority task preempts the low-priority one indefinitely. The kernel mitigates this with rt_mutex id which implements Priority inheritance – temporarily boosting the lock holder's priority to that of the highest-priority waiter.

RT synchronization

[edit | edit source]

โšฒ APIs

migrate_disable id + spin_lock id
local_lock id calls migrate_disable(); rt_spin_lock id(this_cpu_ptr id((__lock)));

๐Ÿ“– References

Usage of migrate_disable
PREEMPT_RT caveats: spinlock_t, rwlock_t, migrate_disable and local_lock doc


โš™๏ธ Internals

Spinlock

linux/spinlock_rt.h inc used via linux/spinlock_types.h inc
spinlock_t id
rt_mutex_base id
rt_spin_lock id ...
__rt_spin_lock id ...
rtlock_lock id ...
kernel/locking/spinlock_rt.c src – RT-aware spinlock implementation

RT Mutex

linux/rtmutex.h inc used via linux/mutex_types.h inc
rt_mutex_base id
rt_mutex id
rt_mutex_lock id ...
kernel/locking/rtmutex_api.c src – RT mutex kernel API
kernel/locking/rtmutex_common.h src – RT mutex internal definitions
kernel/locking/rtmutex.c src – RT mutex core with priority inheritance

rwbase_rt

linux/rwbase_rt.h inc used via linux/rwlock_types.h inc
rwlock_t id
rwbase_rt id – used to implement real-time read/write locks
rt_read_trylock id ...
kernel/locking/rwbase_rt.c src – RT rw_semaphore/rwlock base
kernel/locking/spinlock_rt.c src – RT-aware spinlock implementation

Testing RT capabilities

[edit | edit source]

The testing process for Real-Time Linux typically involves several key aspects. First and foremost, it is crucial to verify the accuracy and stability of the system's timekeeping mechanisms. Precise time management is fundamental to real-time applications, and any inaccuracies can lead to timing errors and compromise the system's real-time capabilities.

Another essential aspect of testing is evaluating the system's scheduling algorithms. Real-Time Linux employs advanced scheduling policies to prioritize critical tasks and ensure their timely execution. Testing the scheduler involves assessing its ability to allocate resources efficiently, handle task prioritization correctly, and prevent resource contention or priority inversion scenarios.

Furthermore, latency measurement is a critical part of Real-Time Linux testing. Latency refers to the time delay between the occurrence of an event and the system's response to it. In real-time applications, minimizing latency is crucial to achieving timely and predictable behavior. Testing latency involves measuring the time it takes for the system to respond to various stimuli and identifying any sources of delay or unpredictability.

Additionally, stress testing plays a significant role in assessing the system's robustness under heavy workloads. It involves subjecting the Real-Time Linux system to high levels of concurrent activities, intense computational loads, and input/output operations to evaluate its performance, responsiveness, and stability. Stress testing helps identify potential bottlenecks, resource limitations, or issues that might degrade the real-time behavior of the system.

RTLA โ€“ The realtime Linux analysis tool:
rtla timerlat doc – CLI for the kernel's timerlat tracer doc
rtla osnoise doc – CLI for the kernel's osnoise tracer doc.
Kernel function run_osnoise id measures time with function trace_clock_local id in loop.
rtla hwnoise doc – CLI for the osnoise tracer doc with interrupts disabled
Implementation: tools/tracing/rtla src and kernel/trace/trace_osnoise.c src
Linux scheduling latency debug and analysis
RT-Tests
[edit | edit source]
RT-Tests, source, @gitlab
cyclictest
some RT-Tests man pages:
cyclictest – measures man 2 clock_nanosleep or man 2 nanosleep delay
hwlatdetect – CLI for /sys/kernel/tracing/hwlat_detector doc / kernel/trace/trace_hwlat.c src. Kernel function kthread_fn id measures time delays with function trace_clock_local id in loop.
oslat – measures delay with RDTSC in busy loop
hackbench – scheduler benchmark/stress test
ftrace
[edit | edit source]

Testing latencies with the ftrace - Function Tracer.

tracing_max_latency
the irqsoff doc, preemptoff doc, preemptirqsoff doc tracers
tools/tracing/latency src – latency measurement tools
CONFIG_IRQSOFF_TRACER id – interrupts-off latency tracer
CONFIG_PREEMPT_TRACER id – preemption-off latency tracer
CONFIG_SCHED_TRACER id – scheduling latency tracer
Other tests
[edit | edit source]
man 1 perf-intel-pt โ€“ Intel Processor Trace for low-overhead instruction-level tracing, tools/perf/Documentation/perf-intel-pt.txt src
Using rtla with perf processor trace
RT Tracing Tools with eBPF
realtime ltp
https://www.latencytop.org/, kernel/latencytop.c src
rteval – RT workload and latency evaluation in a container


RT optimizations

[edit | edit source]
CONFIG_PSI_DEFAULT_DISABLED id – disable PSI doc
Check: ls /proc/pressure/ should fail


๐Ÿ“š Further reading:

https://lore.kernel.org/linux-rt-users/
https://lore.kernel.org/linux-trace-kernel/


๐Ÿ“– References

Real-time preemption doc
Documentation for /proc/sys/kernel/ doc – sched_rt_period_us, sched_rt_runtime_us
https://realtime-linux.org/
Getting Started with PREEMPT_RT Guide
A Checklist for Real-Time Applications in Linux
the Real-Time Linux wiki
CPU partitioning and isolation
linux-stable-rt.git
linux-rt-devel.git


๐Ÿ“š Further reading about real-time Linux:

News from PREEMPT_RT – LPC 2025, post-mainline developments
https://deepwiki.com/torvalds/linux/2.1-process-scheduler
Introduction to Real-Time Linux: Unleashing Deterministic Computing
Power Management and Scheduling in the Linux Kernel (OSPM)
Realtime@LWN
Realtime kernel patchset, Arch Linux
https://www.kernel.org/pub/linux/kernel/projects/rt/ - RT patches for upstream kernel
High Precision Event Timer (HPET)
Demystifying the Real-Time Linux Scheduling Latency
RHEL for RT
Understanding RHEL for RT – affinity, SCHED_DEADLINE cpusets, RT socket options, timerlat, runtime monitors
Optimizing for low latency:
SCHED_DEADLINE parameters
BIOS tuning – disable power management, error correction, SMI
Runtime verification – monitors and reactors
CPU isolation – tuned profiles, isolated_cores, nohz_full
RCU callback offloading
Scheduling problems – throttling, starvation
Linux subsystems related to real-time
Linux kernel scheduling and preemption
Interrupts
Deferred works
Non-maskable interrupt handler (NMI)
System management interrupt (SMI)
man 7 sched
latency @ LKML
PREEMPT_RT @ LKML
QA about PREEMPT_RT, LPC'23, State of the onion, pdf

๐Ÿ’พ Historical

The PREEMPT_RT patch has been fully merged into the mainline Linux kernel, starting from version 6.12.


Synchronization

[edit | edit source]

Thread synchronization is defined as a mechanism which ensures that two or more concurrent processes or threads do not simultaneously execute some particular program segment known as mutual exclusion (mutex). When one thread starts executing the critical section (serialized segment of the program) the other thread should wait until the first thread finishes. If proper synchronization techniques are not applied, it may cause a race condition where, the values of variables may be unpredictable and vary depending on the timings of context switches of the processes or threads.

User space synchronization

[edit | edit source]

POSIX Timers

[edit | edit source]

โšฒ APIs

man 2 timer_create โ€“ creates a POSIX timer
man 2 timer_settime โ€“ starts or modifies a timer
man 2 timer_gettime โ€“ retrieves the remaining time of a timer
man 2 timer_delete โ€“ deletes a POSIX timer
man 2 clock_nanosleep โ€“ suspends execution for a specified time

โš™๏ธ Internals

linux/posix-timers.h inc
kernel/time/itimer.c src – interval timer (setitimer/getitimer)
kernel/time/posix-timers.c src – POSIX clock and timer operations
kernel/time/posix-cpu-timers.c src – per-process/thread CPU timers
posix_cpu_timer_set id โ€“ function setting up CPU timers


Futex

[edit | edit source]

A man 2 futex โ†ช do_futex id (short for "Fast User space muTex") is a kernel system call that programmers can use to implement basic locking, or as a building block for higher-level locking abstractions such as semaphores and POSIX mutexes or condition variables.

A futex consists of a kernel space wait queue that is attached to an aligned integer in user space. Multiple processes or threads operate on the integer entirely in user space (using atomic operations to avoid interfering with one another), and only resort to relatively expensive system calls to request operations on the wait queue (for example to wake up waiting processes, or to put the current process on the wait queue). A properly programmed futex-based lock will not use system calls except when the lock is contended; since most operations do not require arbitration between processes, this will not happen in most cases.


The basic operations of futexes are based on only two central operations futex_wait id and futex_wake id though implementation has more operations for more specialized cases.

WAIT (addr, val) checks if the value stored at the address addr is val, and if it is puts the current thread to sleep.
WAKE (addr, val) wakes up val number of threads waiting on the address addr.


โšฒ API

uapi/linux/futex.h inc
linux/futex.h inc

โš™๏ธ Internals: kernel/futex src

๐Ÿ”จ stress-ng --futex

๐Ÿ“– References

Futex
man 7 futex
Futex API reference doc
futex ltp

File locking

[edit | edit source]

โšฒ API: man 2 flock


Semaphore

[edit | edit source]

๐Ÿ’พ History: Semaphore is part of System V IPC man 7 sysvipc

โšฒ API

man 2 semget
man 2 semctl
man 2 semop


โš™๏ธ Internals: ipc/sem.c src

๐Ÿ”จ stress-ng --sem

Kernel space synchronization

[edit | edit source]

For kernel mode synchronization Linux provides three categories of locking primitives: sleeping, per CPU local locks and spinning locks.

rust/kernel/sync.rs src โ€“ Rust bindings for locking primitives


Read-Copy-Update

[edit | edit source]

Common mechanism to solve the readersโ€“writers problem is the read-copy-update (RCU) algorithm. Read-copy-update implements a kind of mutual exclusion that is wait-free (non-blocking) for readers, allowing extremely low overhead. However, RCU updates can be expensive, as they must leave the old versions of the data structure in place to accommodate pre-existing readers.


โšฒ The core API in linux/rcupdate.h inc is quite small:

rcu_read_lock id marks an RCU-protected data structure so that it won't be reclaimed for the full duration of that critical section.
rcu_read_unlock id is used by a reader to inform the reclaimer that the reader is exiting an RCU read-side critical section. Note that RCU read-side critical sections may be nested and/or overlapping.
synchronize_rcu id blocks until all pre-existing RCU read-side critical sections on all CPUs have completed. Note that synchronize_rcu will not necessarily wait for any subsequent RCU read-side critical sections to complete.


For example, consider the following sequence of events:

CPU 0 CPU 1 CPU 2
1. rcu_read_lock()
2. enters synchronize_rcu()
3. rcu_read_lock()
4. rcu_read_unlock()
5. exits synchronize_rcu()
6. rcu_read_unlock()
RCU API communications between the reader, updater, and reclaimer
Since synchronize_rcu is the API that must figure out when readers are done, its implementation is key to RCU. For RCU to be useful in all but the most read-intensive situations, synchronize_rcu's overhead must also be quite small.
Alternatively, instead of blocking, synchronize_rcu may register a callback to be invoked after all ongoing RCU read-side critical sections have completed. This callback variant is called call_rcu id in the Linux kernel.
rcu_assign_pointer id - The updater uses this function to assign a new value to an RCU-protected pointer, in order to safely communicate the change in value from the updater to the reader. This function returns the new value, and also executes any Memory barrier instructions required for a given CPU architecture. Perhaps more importantly, it serves to document which pointers are protected by RCU.
rcu_dereference id - The reader uses this function to fetch an RCU-protected pointer, which returns a value that may then be safely dereferenced. It also executes any directives required by the compiler or the CPU, for example, a volatile cast for gcc, a memory_order_consume load for C/C++11 or the memory-barrier instruction required by the old DEC Alpha CPU. The value returned by rcu_dereference is valid only within the enclosing RCU read-side critical section. As with rcu_assign_pointer, an important function of rcu_dereference is to document which pointers are protected by RCU.

The RCU infrastructure observes the time sequence of rcu_read_lock, rcu_read_unlock, synchronize_rcu, and call_rcu invocations in order to determine when (1) synchronize_rcu invocations may return to their callers and (2) call_rcu callbacks may be invoked. Efficient implementations of the RCU infrastructure make heavy use of batching in order to amortize their overhead over many uses of the corresponding APIs.

โšฒ API

rcu_nocbs – no-callback CPUs
linux/rcupdate.h inc
linux/rculist.h inc – RCU-protected linked list operations


โš™๏ธ Internals

kernel/rcu src – read-copy-update implementation


๐Ÿ“– References

Avoiding Locks: Read Copy Update doc
RCU concepts doc
RCU initialization


๐Ÿ“š Further reading

Reduce synchronize_rcu() latency

Sleeping locks

[edit | edit source]
Mutexes
[edit | edit source]

โšฒ API

linux/mutex.h inc
linux/completion.h inc
mutex id has owner and usage constraints, easier to debug than semaphore
rt_mutex id blocking mutual exclusion locks with priority inheritance (PI) support
ww_mutex id Wound/Wait mutexes: blocking mutual exclusion locks with deadlock avoidance
rw_semaphore id readersโ€“writer semaphores
percpu_rw_semaphore id
completion id - use completion for synchronization task with ISR and task or two tasks.
wait_for_completion id
complete id

๐Ÿ”จ stress-ng --mutex

๐Ÿ’พ Historical

semaphore id - use mutex instead semaphore if possible
linux/semaphore.h inc
linux/rwsem.h inc


๐Ÿ“– References

Completions - โ€œwait for completionโ€ barrier APIs doc
Mutex API reference doc
LWN: completion events

per CPU local lock

[edit | edit source]

On normal preemptible kernel local_lock calls preempt_disable id. On RT preemptible kernel local_lock calls migrate_disable id and spin_lock id. Any changes applied to spinlock_t also apply to local_lock.


โšฒ API

linux/local_lock.h inc
local_lock id, preempt_disable id
local_lock_irqsave id, local_irq_save id
etc


๐Ÿ“– References

local_lock doc
PREEMPT_RT caveats: spinlock_t, rwlock_t, migrate_disable and local_lock doc
Proper locking under a preemptive kernel doc
Local locks in the kernel


Spinning locks

[edit | edit source]

a spinlock is a lock which causes a thread trying to acquire it to simply wait in a loop ("spin") while repeatedly checking if the lock is available. Since the thread remains active but is not performing a useful task, the use of such a lock is a kind of busy waiting. Once acquired, spinlocks will usually be held until they are explicitly released, although in some implementations they may be automatically released if the thread being waited on (that which holds the lock) blocks, or "goes to sleep".

Spinlocks are commonly used inside kernels because they are efficient if threads are likely to be blocked for only short periods. However, spinlocks become wasteful if held for longer durations, as they may prevent other threads from running and require rescheduling. ๐Ÿ‘ For example kobj_kset_join id uses spinlock to protect assess to the linked list.

Enabling and disabling of kernel preemption replaced spinlocks on uniprocessor systems (disabled CONFIG_SMP id). Most spinning locks becoming sleeping locks in the CONFIG_PREEMPT_RT id kernels.


โšฒ API

linux/spinlock.h inc
spinlock_t id
raw_spinlock_t id
linux/bit_spinlock.h inc
bit_spin_lock id


๐Ÿ“– References

Introduction to spinlocks
Queued spinlocks

A seqlock (short for "sequential lock") is a special locking mechanism used in Linux for supporting fast writes of shared variables between two parallel operating system routines. It is a special solution to the readersโ€“writers problem when the number of writers is small.

It is a reader-writer consistent mechanism which avoids the problem of writer starvation. A seqlock_t id consists of storage for saving a sequence counter seqcount_t id/seqcount_spinlock_t in addition to a lock. The lock is to support synchronization between two writers and the counter is for indicating consistency in readers. In addition to updating the shared data, the writer increments the sequence counter, both after acquiring the lock and before releasing the lock. Readers read the sequence counter before and after reading the shared data. If the sequence counter is odd on either occasion, a writer had taken the lock while the data was being read and it may have changed. If the sequence counters are different, a writer has changed the data while it was being read. In either case readers simply retry (using a loop) until they read the same even sequence counter before and after.


โšฒ API

seqlock_t id
DEFINE_SEQLOCK id, seqlock_init id, read_seqlock_excl id, write_seqlock id
seqcount_t id
seqcount_init id, read_seqcount_begin id, read_seqcount_retry id, write_seqcount_begin id, write_seqcount_end id
linux/seqlock.h inc

๐Ÿ‘ Example: mount_lock id, defined in fs/namespace.c src


๐Ÿ“– References

Sequence counters and sequential locks doc
SeqLock

Spinning or sleeping locks

[edit | edit source]
normal on preempt RT
spinlock_t, raw_spinlock_t rt_mutex_base, rt_spin_lock, sleeping
rwlock_t spinning sleeping
local_lock preempt_disable migrate_disable, rt_spin_lock, sleeping

Low level

[edit | edit source]

The compiler might optimize away or reorder writes to variables leading to unexpected behavior when variables are accessed concurrently by multiple threads.

โšฒ API

asm-generic/rwonce.h inc – prevent the compiler from merging or refetching reads or writes.
linux/compiler.h inc
barrier id – prevents the compiler from reordering instructions around the barrier
asm-generic/barrier.h inc – generic barrier definitions
arch/x86/include/asm/barrier.h src – force strict CPU ordering
mb id – ensures that all memory operations before the barrier are completed before any memory operations after the barrier are started


โš™๏ธ Internals

Atomics doc
linux/atomic.h inc – atomic operations wrapper
asm-generic/atomic.h inc
linux/atomic/atomic-instrumented.h inc
atomic_dec_and_test id ...


๐Ÿ“š Further reading

volatile – prevents the compiler from optimizations
Memory barrier – enforces an ordering constraint on memory operations

๐Ÿ”จ stress-ng --lockbus


โš™๏ธ Locking internals

linux/lockdep.h inc – runtime locking correctness validator
linux/debug_locks.h inc
lib/locking-selftest.c src – locking correctness self-tests
kernel/locking src – locking primitives
mutex_waiter id, timer_list id, wait_queue_head_t id
kernel/locking/locktorture.c src – module-based torture test facility for locking


๐Ÿ“– Locking references

locking doc
Lock types and their rules doc
๐Ÿ˜ด sleeping locks doc
mutex id, rt_mutex id, semaphore id, rw_semaphore id, ww_mutex id, percpu_rw_semaphore id
on preempt RT: local_lock, spinlock_t, rwlock_t
๐Ÿ˜ตโ€๐Ÿ’ซ spinning locks doc:
raw_spinlock_t, bit spinlocks
on non preempt RT: spinlock_t, rwlock_t
Unreliable Guide To Locking doc
LKMPG: Synchronization
Synchronization primitives


โšฒ UAPI

uapi/linux/time.h inc
timespec id – nanosecond resolution
timeval id – microsecond resolution
timezone id
...
uapi/linux/time_types.h inc
__kernel_timespec id – nanosecond resolution, used in syscalls
...

โšฒ API

linux/delay.h inc – busy-wait delay functions for timing control
linux/sched/clock.h inc
sched_clock id
...
linux/time.h inc
tm id
get_timespec64 id
...
linux/ktime.h inc
ktime_t id – nanosecond scalar representation for kernel time values
ktime_sub id
...
linux/timekeeping.h inc
ktime_get id, ktime_get_ns id
ktime_get_real id
...
linux/time64.h inc
timespec64 id
time64_t id
ns_to_timespec64 id
timespec64_sub id
ktime_to_timespec64 id
...
uapi/linux/rtc.h inc
linux/jiffies.h inc


โš™๏ธ Internals

kernel/time src – timekeeping, timers and clocks
timekeeper id – central timekeeping state
tkr_mono id – monotonic clock, frequency corrected by NTP for accurate real-world seconds
man 8 chronyd โ†’ man 2 adjtimex โ†ช sys_adjtimex id
tkr_raw id – raw monotonic clock, no NTP correction, drifts with crystal error
update_wall_time id โ† tick_periodic id โ†’ timekeeping_advance id (blocks readers with write_seqcount_begin id):
tk_clock_read id – reads clocksource hardware
logarithmic_accumulation id – accumulates ticks in doubling steps (efficient for NO_HZ)
timekeeping_adjust id – corrects mult to steer toward NTP frequency
accumulate_nsecs_to_secs id – rolls nanoseconds into seconds
timekeeping_update_from_shadow id – publishes shadow timekeeper to live
update_vsyscall id – copies time data to vDSO page for userspace man 2 clock_gettime without syscall
update_fast_timekeeper id – NMI-safe copy via write_seqcount_latch_begin id (two copies, ktime_get_mono_fast_ns id and other ktime_get*_fast readers spin on read_seqcount_latch_retry id)
ktime_get id and all ktime_get* readers spin on read_seqcount_retry id until consistent
ktime_get id = tkr_mono id.base + timekeeping_get_ns id
timekeeping_get_ns id โ†’ tk_clock_read id, timekeeping_cycles_to_ns id – converts cycles to ns (delta only, added to base by caller)
tk_clock_read id โ†’ arch_inlined_clocksource_read id โ†’ rdtsc_ordered id – x86 TSC fast path via static key
timekeeping_get_ns id and rdtsc_ordered id are safe to trace timekeeping (no seqcount), unlike ktime_get id which would block on read_seqcount_retry id

๐Ÿ”จ stress-ng --timer, --hrtimers

PTP provides sub-microsecond clock synchronization over a network using hardware timestamping.

โšฒ API

/sys/class/ptp/ – PTP hardware clock devices
ptp4l – PTP boundary/ordinary clock daemon
phc2sys – synchronize system clock to PTP hardware clock
uapi/linux/ptp_clock.h inc

โš™๏ธ Internals

drivers/ptp src – PTP hardware clock drivers

๐Ÿ“– References

PTP hardware clock infrastructure for Linux doc
ktime accessors doc
Clock sources, Clock events, sched_clock() and delay timers doc
Time and timer routines doc
Year 2038 problem


Interrupts

[edit | edit source]

An interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention. An interrupt alerts the processor to a high-priority condition requiring the interruption of the current code the processor is executing. The processor responds by suspending its current activities, saving its state, and executing a function called an interrupt handler (or an interrupt service routine, ISR) to deal with the event. This interruption is temporary, and, after the interrupt handler finishes, the processor resumes normal activities.

There are two types of interrupts: hardware interrupts and software interrupts. Hardware interrupts are used by devices to communicate that they require attention from the operating system. For example, pressing a key on the keyboard or moving the mouse triggers hardware interrupts that cause the processor to read the keystroke or mouse position. Unlike the software type, hardware interrupts are asynchronous and can occur in the middle of instruction execution, requiring additional care in programming. The act of initiating a hardware interrupt is referred to as an interrupt request - IRQ โ†ช IDT โ†ช common_interrupt id on x86.

A software interrupt is caused either by an exceptional condition in the processor itself, or a special instruction in the instruction set which causes an interrupt when it is executed. The former is often called a trap (โš™๏ธ do_trap id) or exception and is used for errors or events occurring during program execution that are exceptional enough that they cannot be handled within the program itself. For example, if the processor's arithmetic logic unit is commanded to divide a number by zero, this impossible demand will cause a divide-by-zero exception (โš™๏ธ X86_TRAP_DE id), perhaps causing the computer to abandon the calculation or display an error message. Software interrupt instructions function similarly to subroutine calls and are used for a variety of purposes, such as to request services from low-level system software such as device drivers. For example, computers often use software interrupt instructions to communicate with the disk controller to request data be read or written to the disk.

Each interrupt has its own interrupt handler. The number of hardware interrupts is limited by the number of interrupt request (IRQ) lines to the processor, but there may be hundreds of different software interrupts.


โšฒ API

/proc/interrupts
man 1 irqtop – utility to display kernel interrupt information
irqbalance – distribute hardware interrupts across processors on a multiprocessor system
There are many ways to request ISR, two of them
devm_request_threaded_irq id – preferable, managed device with threaded ISR
devm_request_irq id – managed version
request_irq id
request_threaded_irq id
free_irq id
linux/interrupt.h inc – main interrupt support header
irqaction id – contains handler functions
rust/kernel/irq.rs src โ€“ Rust bindings
linux/irq.h inc
irq_data id
linux/irqflags.h inc
irqs_disabled id
local_irq_save id ...
local_irq_disable id ...
linux/irqdesc.h inc
irq_desc id
linux/irqdomain.h inc
irq_domain id – hardware interrupt number translation object
irq_domain_get_irq_data id
linux/msi.h inc – Message Signaled Interrupts
msi_desc id
Structure of structures:
irq_desc id is container of
irq_data id
irq – interrupt number
irq_common_data id
list of irqaction id


โš™๏ธ Internals

kernel/irq/settings.h src – IRQ descriptor status flags
kernel/irq src – generic IRQ handling
kernel/irq/internals.h src – IRQ subsystem internal functions
ls /sys/kernel/debug/irq/domains/
x86_vector_domain id, x86_vector_domain_ops id
irq_chip id
load_idt id – load Interrupt Descriptor Table
arch/x86/include/asm/idtentry.h src – interrupt entry/exit definitions
arch/x86/include/asm/hw_irq.h src – x86 hardware IRQ definitions
irq_entries_start id – hardware IRQ entry stubs
arch/x86/kernel/irq.c src – x86 interrupt handling
common_interrupt id – handles all normal device IRQs on x86
arch/x86/kernel/apic src – APIC
arch/x86/kernel/apic/apic.c src – local APIC core (timer, calibration, spurious interrupt)
arch/x86/kernel/apic/io_apic.c src – I/O APIC, routes device IRQs to CPUs
arch/x86/kernel/apic/x2apic_cluster.c src – x2APIC (>256 CPUs)
arch/x86/kernel/apic/ipi.c src – IPI, see IPI
arch/x86/kernel/apic/hw_nmi.c src – hardware NMI watchdog via APIC
arch/x86/kernel/apic/vector.c src – IRQ vector allocation
arch/x86/kernel/apic/msi.c src – MSI via APIC

๐Ÿ“– References

IRQs doc
The irq_domain interrupt number mapping library doc
Linux generic IRQ handling doc
Message Signaled Interrupts: The MSI Driver Guide doc
Lock types and their rules doc
Hard IRQ Context doc
Interrupts


๐Ÿ‘ Examples

dummy_irq_chip id – dummy interrupt chip implementation
lib/locking-selftest.c src – locking correctness self-tests


IRQ affinity

[edit | edit source]

โšฒ API

/proc/irq/default_smp_affinity
/proc/irq/*/smp_affinity and /proc/irq/*/smp_affinity_list


Common types and functions:

struct irq_affinity id – description for automatic irq affinity assignments, see devm_platform_get_irqs_affinity id
struct irq_affinity_desc id – interrupt affinity descriptor, see irq_update_affinity_desc id, irq_create_affinity_masks id
irq_set_affinity id
irq_get_affinity_mask id
irq_can_set_affinity id
irq_set_affinity_hint id
irqd_affinity_is_managed id
irq_data_get_affinity_mask id
irq_data_get_effective_affinity_mask id
irq_data_update_effective_affinity id
irq_set_affinity_notifier id
irq_affinity_notify id
irq_chip_set_affinity_parent id
irq_set_vcpu_affinity id


๐Ÿ› ๏ธ Utilities

irqbalance โ€“ distributes hardware interrupts across CPUs


๐Ÿ“– References

SMP IRQ affinity doc
IRQ affinity, LF
managed_irq kernel parameter, @LKML
irqaffinity kernel parameter, @LKML


Non-maskable interrupts

[edit | edit source]

โšฒ API

linux/nmi.h inc
in_nmi id
touch_nmi_watchdog id
...
trace/events/nmi.h inc
arch/x86/include/asm/nmi.h src – x86 NMI handler registration
register_nmi_handler id
unregister_nmi_handler id


โš™๏ธ Internals

arch/x86/kernel/nmi.c src – x86 NMI handler
arch/x86/kernel/apic/hw_nmi.c src – hardware NMI watchdog via APIC
arch/x86/kernel/nmi_selftest.c src – NMI IPI self-tests


๐Ÿ“– References

NMI Trace Events doc


๐Ÿ“š Further reading

Non-maskable interrupt handler (NMI)


๐Ÿ“š Further reading about interrupts

IDT – Interrupt descriptor table
LGDT/LIDT – Load Global/Interrupt Descriptor Table Register asm instruction

Deferred works

[edit | edit source]

Scheduler context

[edit | edit source]

kthread work

[edit | edit source]

This framework simplifies the use of kernel kthreads. A kthread_work id item can be queued with kthread_queue_work id and flushed using kthread_flush_work id. All queued kthread_work items are processed by a dedicated kernel thread executing the kthread_worker_fn id function.

โšฒ API

kthread_work id – contains kthread_work_func_t id to execute
kthread_init_work id
kthread_flush_work id
kthread_worker id – links a kthread_work and a task
kthread_run_worker id – creates and wakes a kthread worker
kthread_create_worker id
kthread_flush_worker id
kthread_destroy_worker id
kthread_queue_work id – queues a kthread_work on a kthread_worker


โš™๏ธ Internals

__kthread_create_worker_on_node id
kthread_worker_fn id – executes work's function


๐Ÿ‘ Example usages

watchdog_kworker id, pwq_release_worker id, pump_messages id

Threaded IRQ

[edit | edit source]

โšฒ API devm_request_threaded_irq id, request_threaded_irq id ISR should return IRQ_WAKE_THREAD to run thread function

โš™๏ธ Internals

setup_irq_thread id, irq_thread id
kernel/irq/manage.c src – IRQ request, free and affinity management

๐Ÿ“– References

request_threaded_irq doc


Work and workqueue

[edit | edit source]

Generic async execution with shared worker pool.

โšฒ API

PF_WQ_WORKER id – workqueue worker process flag
linux/workqueue.h inc, linux/workqueue_types.h inc
rust/kernel/workqueue.rs src โ€“ Rust bindings
work_struct id, INIT_WORK id
delayed_work id, INIT_DELAYED_WORK id, cancel_delayed_work_sync id
workqueue_struct id
devm_alloc_workqueue id
alloc_workqueue id
destroy_workqueue id
schedule_work id – queues work on the system workqueue โ†ฏ
queue_work id – queues work on a workqueue
queue_work_on id – on a specific CPU
show_all_workqueues id
show_one_workqueue id
system_power_efficient_wq id ...


๐Ÿ‘ Example usage samples/ftrace/sample-trace-array.c src


โš™๏ธ Internals

kernel/workqueue.c src – generic async execution with shared worker pool
workqueue_init id
create_worker id
worker_thread id
process_one_work id
format_worker_id id – names kworker kthreads
pool_workqueue id
worker_pool id


๐Ÿ“– References

Concurrency Managed Workqueue doc
LKMPG: Work queues

Interrupt context

[edit | edit source]
linux/irq_work.h inc – run callbacks from hardirq or NMI context where normal work queues can't be used
irq_work_queue id – enqueue work on the current CPU, triggers IRQ_WORK_VECTOR id IPI if needed
irq_work_sync id – wait for completion
kernel/irq_work.c src – irq_work implementation
๐Ÿ‘ samples/trace_printk/trace-printk.c src

Timers

[edit | edit source]

Not to be confused with POSIX timer โ€“ userspace API, watchdog timer โ€“ hang detection, local APIC timer โ€“ per-CPU hardware, drives the tick.

timer softirq
[edit | edit source]

Not to be confused with nanosecond-resolution high-resolution timer.

This timer is a softirq for periodical tasks with jiffies resolution. Also known as kernel timer or timer wheel.

โšฒ API

linux/timer.h inc
timer_list id, DEFINE_TIMER id, timer_setup id
mod_timer id — sets expiration time in jiffies.
timer_delete id


โš™๏ธ Internals

kernel/time/timer.c src โ€“ kernel internal timers
timer_bases id โ€“ per-CPU array of timer_base id (timing wheel):
BASE_LOCAL โ€“ pinned to this CPU (TIMER_PINNED id)
BASE_GLOBAL โ€“ can be run remotely by migrator via timer_expire_remote id
BASE_DEF โ€“ deferrable, can be delayed indefinitely
run_timer_softirq id โ€“ TIMER_SOFTIRQ id handler
__run_timer_base id โ€“ iterate expired timers and call callbacks


๐Ÿ‘ Examples

input_enable_softrepeat id and input_start_autorepeat id


๐Ÿ“š References

Time and timer routines doc
timer_init_key ... doc
High-resolution timer
[edit | edit source]

Not to be confused with jiffies-resolution timer softirq.

โšฒ API

/proc/timer_list
/proc/sys/kernel/timer_migration doc โ€“ enable/disable hrtimer migration
linux/hrtimer_defs.h inc
linux/hrtimer.h inc
hrtimer id, hrtimer.function — callback
hrtimer_setup id
hrtimer_start id — starts a timer with nanosecond resolution
hrtimer_cancel id


๐Ÿ‘ Examples alarm_init id, watchdog_enable id


โš™๏ธ Internals

CONFIG_HIGH_RES_TIMERS id
kernel/time/tick-internal.h src – tick and timer internal definitions
hrtimer_bases id โ€“ per-CPU hrtimer_cpu_base id, contains 8 clock bases:
hrtimer_clock_base id โ€“ timerqueue per clock type per CPU
hrtimer_base_type id โ€“ MONOTONIC, REALTIME, BOOTTIME, TAI (ร— hardirq + softirq = 8)
kernel/time/hrtimer.c src โ€“ high-resolution timer implementation
hrtimer_interrupt id โ€“ called from clock event device, expires hardirq timers
__hrtimer_run_queues id โ€“ walk timerqueue, call expired callbacks
hrtimer_run_softirq id โ€“ HRTIMER_SOFTIRQ id handler, expires HRTIMER_MODE_SOFT timers
__hrtimer_run_queues id
kernel/time/itimer.c src โ€“ interval timers
kernel/time/timer_list.c src – /proc/timer_list debugfs


๐Ÿ“š HR timers references

High-resolution timers doc
hrtimers - subsystem for high-resolution kernel timers doc
high resolution timers and dynamic ticks design notes doc
Tick and NO_HZ
[edit | edit source]

The tick is the periodic timer interrupt that drives scheduling, timekeeping, and RCU. The NO_HZ subsystem reduces or eliminates tick interrupts to save power and reduce latency.

โšฒ API

/sys/devices/system/cpu/nohz_full โ€“ active nohz_full CPUs
nohz_full= boot parameter โ€“ list of CPUs to run tickless
linux/tick.h inc โ€“ tick control API
tick_nohz_full_running id โ€“ true if any CPU runs tickless
tick_nohz_full_cpu id โ€“ true if given CPU runs tickless
enum tick_dep_bits id โ€“ reasons a CPU/task/signal may need the tick (posix timer, perf events, sched, unstable clock, RCU, RCU expedited)
tick_nohz_dep_set id ... โ€“ modify a global tick dependency bit, used by perf for unstable clocks; kicks all full-nohz CPUs to restart their tick
sched_tick_remote id โ€“ remote CPU updates scheduler stats (load, timeslice) for nohz_full CPUs via delayed work
/proc/sys/kernel/timer_migration doc โ€“ enable/disable hrtimer migration

๐Ÿช› Compile-time configurations (kernel/time/Kconfig src)

CONFIG_HZ_PERIODIC id โ€“ constant-rate tick, always firing
CONFIG_NO_HZ_IDLE id โ€“ stop tick when CPU is idle (default on most distros)
CONFIG_NO_HZ_FULL id โ€“ stop tick even when running a single task, for RT and latency-sensitive workloads, see CPU isolation

โš™๏ธ Internals

kernel/time/tick-common.c src โ€“ periodic tick setup
kernel/time/tick-oneshot.c src โ€“ oneshot mode for hrtimers and NO_HZ
kernel/time/tick-sched.c src โ€“ NO_HZ tick scheduling logic
tick_nohz_handler id โ€“ hrtimer callback driving the tick, rearmed at TICK_NSEC until idle/full-dynticks stops it
tick_nohz_init id โ€“ enable full nohz on boot if requested and supported
kernel/time/tick-broadcast.c src โ€“ broadcast tick for CPUs in deep idle where local timer stops (C3+)
tick_dependency:
sched_update_tick_dependency id โ€“ modifies the TICK_DEP_BIT_SCHED id scheduler tick dependency bit in tick_dep_mask id
sched_can_stop_tick id โ€“ true if a runqueue has at most one runnable task and can go tickless
can_stop_full_tick id โ€“ decide if a full-dynticks CPU can stop its tick, checking CPU online state and the tick_dep_mask id tick dependencies
check_tick_dependency id โ€“ test one tick dependency mask (global, CPU, task, signal) for a pending reason to keep the tick running
kernel/time/timer_migration.h src, kernel/time/timer_migration.c src โ€“ migrate timer softirq (BASE_GLOBAL) from idle to busy CPUs via hierarchical groups
tmigr_cpu_activate id โ€“ CPU joins migration hierarchy on online
tmigr_handle_remote id โ€“ migrator CPU fires expired timers on behalf of idle CPUs
timer_expire_remote id โ†’ __run_timer_base id
tmigr_update_events id โ€“ propagate timer events up/down the hierarchy
/sys/kernel/debug/tracing/events/timer_migration/ โ€“ tracepoints
/proc/sys/kernel/timer_migration doc โ€“ enable/disable hrtimer migration
timers_migration_enabled id
Used in:
switch_hrtimer_base id โ€“ move hrtimer to target CPU base at enqueue time
get_target_base id โ€“ select hrtimer_cpu_base, migrates to busy CPU if not pinned
get_nohz_timer_target id โ€“ pick busy CPU
hrtimer_prefer_local id

๐Ÿ“– References

NO_HZ: Reducing Scheduling-Clock Ticks doc
Tickless kernel, RT wiki
high resolution timers and dynamic ticks design notes doc
Clock infrastructure
[edit | edit source]

Not to be confused with drivers/clk framework โ€“ SoC clock tree management.

Clocksources read current time (passive counters). Clock event devices fire interrupts at a programmed time (active). Together they are the foundation for timekeeping, timers, tick, and NO_HZ.


โšฒ Clocksources โ€“ "what time is it?"

/sys/devices/system/clocksource/clocksource0/current_clocksource
/sys/devices/system/clocksource/clocksource0/available_clocksource
TSC โ€“ fastest, per-CPU, x86
HPET โ€“ system-wide, MMIO
ACPI PM timer โ€“ never stops in any C-state, slow
linux/clocksource.h inc โ€“ clocksource id, clocksource_register_hz id


โšฒ Clock event devices โ€“ "wake me at time X"

linux/clockchips.h inc โ€“ clock_event_device id, clockevents_config_and_register id
Local APIC timer โ€“ per-CPU, fastest, stops in C3+, local_apic_timer_interrupt id
HPET โ€“ system-wide, used as broadcast fallback


โš™๏ธ Internals

kernel/time/clocksource.c src โ€“ clocksource selection and watchdog
kernel/time/clockevents.c src โ€“ clock event device framework
kernel/time/jiffies.c src โ€“ jiffies clocksource (fallback)


๐Ÿ“– Timers references

Timers doc
Better CPU selection for timer expiration

Tasklet

[edit | edit source]

tasklet is a softirq, for time critical operations

โšฒ API is deprecated in favor of threaded IRQs: devm_request_threaded_irq id

tasklet_struct id, tasklet_init id, tasklet_schedule id


โš™๏ธ Internals: tasklet_action_common id HI_SOFTIRQ, TASKLET_SOFTIRQ


Softirq

[edit | edit source]

softirq is internal system facility and should not be used directly. Use tasklet or threaded IRQs

โšฒ API

linux/interrupt.h inc
cat /proc/softirqs
open_softirq id registers softirq_action id
raise_softirq id
tasklet_schedule id
__tasklet_schedule id


โš™๏ธ Internals

kernel/softirq.c src – software interrupt handling
__do_softirq id – main softirq processing loop


๐Ÿ“– References

Introduction to deferred interrupts (Softirq, Tasklets and Workqueues)
Timers and time management
Deferred work, linux-kernel-labs
Chapter 7. Time, Delays, and Deferred Work

CPU specific

[edit | edit source]

๐Ÿ–ฑ๏ธ GUI

tuna – program for tuning running processes


โšฒ API

cat /proc/cpuinfo
/sys/devices/system/cpu/
/sys/devices/system/node/
/sys/cpu/
/sys/fs/cgroup/cpu/
grep -i cpu /proc/self/status
rdmsr – tool for reading CPU machine specific registers (MSR)
man 1 lscpu – display information about the CPU architecture
linux/arch_topology.h inc – arch specific cpu topology information
linux/cpu.h inc – generic cpu definition
linux/cpu_cooling.h inc
linux/cpu_pm.h inc
linux/cpufeature.h inc
arch/x86/include/asm/cpufeature.h src – x86 CPU feature detection
linux/peci-cpu.h inc
linux/sched/cputime.h inc – cputime accounting APIs
linux/clk.h inc – interfaces for managing hardware clocks in device drivers


โš™๏ธ Internals

drivers/base/cpu.c src – CPU driver model subsystem
cpu_dev_init id


Cache

[edit | edit source]
linux/cacheflush.h inc
arch/x86/include/asm/cacheflush.h src: clflush_cache_range id
linux/cache.h inc – cache line alignment macros
____cacheline_aligned id – align to cache line boundary to avoid false sharing
__cacheline_aligned id – same, plus place in .data..cacheline_aligned section
____cacheline_aligned_in_smp id – same, but no-op on uniprocessor builds
__read_mostly id – place in a cache-friendly section for rarely written data
__ro_after_init id – writable during init, read-only after boot (security hardening)
DEFINE_PER_CPU_CACHE_HOT id – per-CPU variable in .data..hot section, used for current_task id, __preempt_count id
L1_CACHE_BYTES id, SMP_CACHE_BYTES id – 64 bytes typically
arch/x86/include/asm/cache.h src – x86 cache line size definitions

๐Ÿ”จ stress-ng --cache

โš™๏ธ Internals

arch/x86/mm/pat/set_memory.c src – page attribute table memory type control
arch/x86/kernel/cpu/mtrr/ src – memory type range register driver

๐Ÿ“š Further reading

MTRR – Memory type range register
CPU cache

This chapter is about multiprocessing and multi-core aspects of Linux kernel.

Key concepts and features of Linux SMP include:

  • Symmetry: In an SMP system, all processors are considered the same without hardware hierarchy in contradiction to use of coprocessors.
  • Load balancing: The Linux kernel employs load balancing mechanisms to distribute tasks evenly among available CPU cores. This prevents any one core from becoming overwhelmed while others remain underutilized.
  • Parallelism: SMP enables parallel processing, where multiple threads or processes can execute simultaneously on different CPU cores. This can significantly improve the execution speed of applications that are designed to take advantage of multiple threads.
  • Thread scheduling: The Linux kernel scheduler is responsible for determining which threads or processes run on which CPU cores and for how long. It aims to optimize performance by minimizing contention and maximizing CPU utilization.
  • Shared memory: In an SMP system, all CPU cores typically share the same physical memory space. This allows processes and threads running on different cores to communicate and share data more efficiently.
  • NUMA – Non-Uniform Memory Access: In larger SMP systems, memory access times might not be uniform due to the physical arrangement of memory banks and processors. Linux has mechanisms to handle NUMA architectures efficiently, allowing processes to be scheduled on CPUs closer to their associated memory.
  • Cache coherency: SMP systems require mechanisms to ensure that all CPU cores have consistent views of memory. Cache coherency protocols ensure that changes made to shared memory locations are correctly propagated to all cores.
  • Scalability: SMP systems can be scaled up to include more CPU cores, enhancing the overall computing power of the system. However, as the number of cores increases, challenges related to memory access, contention, and communication between cores may arise.
  • Kernel and user space: Linux applications running in user space can take advantage of SMP without needing to be aware of the underlying hardware details. The kernel handles the management of CPU cores and resource allocation.


โšฒ API

ps -PLe – lists threads with processor that the thread last executed on (the third column PSR).
man 2 getcpu – determine CPU and NUMA node on which the calling thread is running
man 8 chcpu – configure CPUs
man 3 CPU_SET – macros for manipulating CPU sets
linux/smp.h inc
The most commonly used functions:
crash_smp_send_stop id โ€“ halts all CPUs except the calling one in a crash context
get_cpu id โ€“ disables preemption and returns the current processor ID
panic_smp_self_stop id โ€“ stops the local CPU during a panic while ensuring others halt
put_cpu id โ€“ re-enables preemption after a previous get_cpu call
raw_smp_processor_id id โ€“ returns the current CPU ID without preemption safety
setup_max_cpus id โ€“ sets up the maximum number of CPUs to be brought online
smp_init id โ€“ initializes core SMP structures and state during boot
smp_prepare_boot_cpu id โ€“ prepares the boot CPU during early SMP initialization
smp_prepare_cpus id โ€“ prepares all CPUs for booting before secondary CPUs are started
smp_processor_id id โ€“ returns the ID of the current CPU with preemption checks
smp_send_stop id โ€“ stops all other CPUs in response to critical events
wake_up_all_idle_cpus id โ€“ wakes all idle CPUs to ensure prompt task execution
linux/cpu.h inc
linux/group_cpus.h inc: group_cpus_evenly id – groups all CPUs evenly per NUMA/CPU locality
asm-generic/percpu.h inc
linux/percpu-defs.h inc – basic definitions for percpu areas
this_cpu_ptr id
linux/percpu.h inc
linux/percpu-refcount.h inc
linux/percpu-rwsem.h inc
linux/preempt.h inc
migrate_disable id, migrate_enable id
/sys/bus/cpu
per CPU local_lock
linux/topology.h inc – cpu_to_node id, numa_node_id id
arch/x86/include/asm/topology.h src – x86 NUMA and CPU topology
See also [[../../Memory#NUMA|NUMA memory section]]


โš™๏ธ Internals

boot_cpu_init id activates the first CPU
smp_prepare_cpus id initializes rest CPUs during boot
cpu_number id
CONFIG_SMP id
CONFIG_NUMA id
trace/events/percpu.h inc
drivers/base/cpu.c src – CPU driver model subsystem support
kernel/cpu.c src – CPU hotplug state machine
smpboot
linux/smpboot.h inc
kernel/smpboot.c src – common SMP CPU bringup/teardown
arch/x86/kernel/smpboot.c src – x86 SMP booting
lib/group_cpus.c src – distribute CPUs evenly across groups


๐Ÿ› ๏ธ Utilities

irqbalance โ€“ distributes hardware interrupts across CPUs
man 8 numactl – controls NUMA policy for processes or shared memory


๐Ÿ“– References

Per-CPU Data doc
How CPU topology info is exported via sysfs doc


๐Ÿ“š Further reading

Functionalities of the scheduler TuneD plugin
tuned-adm – command line tool for switching between different tuning profiles


An inter-processor interrupt is a signal sent from one CPU to another to request an action such as rescheduling, TLB flush, or function execution.

โšฒ API

smp_send_reschedule id – sends a reschedule IPI to a target CPU
smp_call_function id – invokes a function on all other CPUs via IPI
smp_call_function_many id – on a specified set of CPUs
smp_call_function_single id – on a single target CPU
smp_call_function_single_async id – asynchronous variant
smp_call_on_cpu id – execute on a specific CPU and wait for result
on_each_cpu id – run a function on all CPUs
on_each_cpu_mask id – on a specified set of CPUs
on_each_cpu_cond_mask id – conditionally on selected CPUs
smp_call_func_t id – callback typedef

โš™๏ธ Internals

trace/events/ipi.h inc
kernel/irq/ipi.c src – generic IPI helpers
ipi_send_single id, ipi_send_mask id
arch/x86/kernel/apic/ipi.c src – x86 IPI via APIC
arch/x86/include/asm/irq_vectors.h src – x86 IPI vector types:
RESCHEDULE_VECTOR id – used by smp_send_reschedule id
CALL_FUNCTION_VECTOR id – used by smp_call_function_many id
CALL_FUNCTION_SINGLE_VECTOR id – used by smp_call_function_single id
IRQ_WORK_VECTOR id – used by irq_work_queue id, see Interrupt context
NMI_VECTOR id – used by watchdog, crash_smp_send_stop id

CPU affinity

[edit | edit source]

Affinity refers to assigning a process or thread to specific CPU cores. This helps control which CPUs execute tasks, potentially improving performance by reducing data movement between cores. It can be managed using system calls or commands. Affinity can be represented as CPU bitmask: cpumask_t id or CPU affinity list: cpulist_parse id.


โšฒ API

man 1 taskset – set or retrieve a process's CPU affinity
grep Cpus_allowed /proc/self/status
man 2 sched_setaffinity man 2 sched_getaffinity – set and get a thread's CPU affinity mask
โ†ช sched_setaffinity id
set_cpus_allowed_ptr id – common kernel function to change a task's affinity mask
linux/cpu_rmap.h inc – CPU affinity reverse-map support
linux/cpumask_types.h inc
struct cpumask, cpumask_t id – CPUs bitmap, can be very big
cpumask_var_t id – type for local cpumask variable, see alloc_cpumask_var id, free_cpumask_var id.
linux/cpumask.h inc – Cpumasks provide a bitmap suitable for representing the set of CPU's in a system, one bit position per CPU number
for_each_possible_cpu id
num_online_cpus id
cpumask_set_cpu id
cpumask_test_cpu id
for_each_cpu id


โš™๏ธ Internals

cpus_mask id – affinity of task_struct id
cpus_allowed id – affinity of cpuset id


๐Ÿ“š Further reading

Processor affinity
Affinity mask

CPU hotplug

[edit | edit source]

CPU hotplugging in Linux refers to the ability to dynamically add or remove CPUs from the system without needing a reboot. This feature is crucial in environments requiring high availability and resource flexibility, such as data centers, virtualized systems, and systems that use power management aggressively.


๐Ÿ—๏ธ Acronyms

BP – Bootstrap Processor
AP – Application Processor


โšฒ API

/sys/devices/system/cpu/cpu*/online
/sys/devices/system/cpu/cpu*/hotplug/
linux/cpu.h inc
add_cpu id ...
linux/cpuhotplug.h inc
cpuhp_state id – CPU hotplug states
cpuhp_setup_state id ... – setups hotplug state callbacks
cpuhp_setup_state_multi id
cpuhp_setup_state_nocalls id
linux/cpuhplock.h inc – CPU hotplug locking
cpus_read_lock id ...
remove_cpu id ...


โš™๏ธ Internals

kernel/cpu.c src – CPU hotplug state machine
cpuhp_state id – from CPUHP_OFFLINE to CPUHP_AP_ACTIVE and CPUHP_ONLINE.
cpuhp_hp_states id
boot_cpu_hotplug_init id
cpuhp_threads_init id
... cpuhp_invoke_callback_range id ...
kernel/irq/cpuhotplug.c src – IRQ migration on CPU hotunplug
drivers/base/cpu.c src – CPU subsystem support
cpu_dev_init id
... cpu_subsys_online id
trace/events/cpuhp.h inc
linux/cpuhplock.h inc


๐Ÿ‘๏ธ Examples

torture_onoff id
tools/testing/selftests/sched_ext/hotplug.c src – sched_ext CPU hotplug test


๐Ÿ“– References

CPU hotplug in the Kernel doc
Introduction doc
Command Line Switches doc
CPU maps doc
Using CPU hotplug doc
The CPU hotplug coordination doc
The CPU hotplug API doc
CPU hotplug state machine doc
CPU online/offline operations doc
Allocating a state doc
Setup of a CPU hotplug state doc
Removal of a CPU hotplug state doc
Multi-Instance state instance management doc
Examples doc
Testing of hotplug states doc
Architectureโ€™s requirements doc
User Space Notification doc
Kernel Inline Documentations Reference doc


๐Ÿ”จ stress-ng --cpu-online

๐Ÿ“š Further reading

CONFIG_CPU_HOTPLUG_STATE_CONTROL id – enables the ability to write incremental steps between "offline" and "online" states to the CPU's sysfs target file, allowing for more granular control of state transitions.
target_store id: cpu_up id/cpu_down id
cpuhotplug, cpuhp @LKML

CPU isolation

[edit | edit source]

CPU isolation ensures that specific tasks run on dedicated CPUs, reducing contention and latency.

Housekeeping CPUs refer to the CPUs that are reserved for various system tasks. See hk_type id.

Isolated CPUs are dedicated to real-time applications, such as DPDK.

โšฒ API

/sys/devices/system/cpu/isolated
/sys/devices/system/cpu/nohz_full
/sys/fs/cgroup/cpuset.cpus.isolated
/sys/fs/cgroup/.../cpuset.cpus.partition
linux/sched/isolation.h inc
hk_type id – housekeeping type
housekeeping_cpumask id – returns CPUs available for housekeeping of a given type
cpu_is_isolated id
linux/cpuset.h inc – cpuset interface
man 7 cpuset – confine processes to processor and memory node subsets


โš™๏ธ Internals

CONFIG_CPU_ISOLATION id
kernel/sched/isolation.c src – housekeeping CPU management
housekeeping_init id, housekeeping_update id
CONFIG_CPUSETS id
kernel/cgroup/cpuset.c src – cpuset cgroup controller
cpuset_init id
cpuset_init_smp id
isolated_cpus id
partition_xcpus_add id, partition_xcpus_del id


๐Ÿ“– References

CPU lists in command-line parameters doc
nohz_full clears housekeeping.cpumasks id for tick, wq, timer, rcu, misc, and kthread in housekeeping_nohz_full_setup id
isolcpus clears housekeeping.cpumasks id for domain (by default), nohz, and managed_irq in housekeeping_isolcpus_setup id
Housekeeping doc
NO_HZ: Reducing Scheduling-Clock Ticks doc
CPUSETS of cgroup v2 doc
CPUSETS of cgroup v1 doc


๐Ÿ“š Further reading

CPU Isolation state of the art, LPC'23
CPU Isolation and IPI interference, LPC'25
CPU Isolation
isolcpus @LKML
housekeeping @LKML
Explicitly Reserved CPU List, Kubernetes Documentation
CPU Partitioning
Scheduler Domains doc – the Scheduler balances CPUs (scheduling groups) within a sched domain
nohz_full @LKML

๐Ÿ’พ Historical since v7.0

cpuset_cpu_is_isolated id – removed, use cpu_is_isolated id instead

Runtime code patching

[edit | edit source]

The kernel patches its own machine code at boot or runtime to optimize hot paths. Static keys patch a NOP to a jump (or vice versa); static calls patch indirect calls to direct calls; alternatives replace instructions based on CPU features.

โšฒ API

linux/jump_label.h inc – static keys
DEFINE_STATIC_KEY_FALSE id – define a key, initially false
static_branch_unlikely id – zero-cost branch check (NOP when key is false)
static_branch_enable id – patch all sites to take the branch (expensive, rare use)
linux/static_call.h inc – static calls
DEFINE_STATIC_CALL id – define a call site with initial target function
static_call id – invoke the patched direct call
static_call_update id – change target function, patch all sites
arch/x86/include/asm/alternative.h src – alternatives
ALTERNATIVE id – replace instructions at boot based on CPU features
arch/x86/include/asm/cpufeatures.h src – X86_FEATURE_* flags


โš™๏ธ Internals

CONFIG_JUMP_LABEL id
kernel/jump_label.c src – static key patching core
arch/x86/kernel/jump_label.c src – x86 static key patching
CONFIG_HAVE_STATIC_CALL id
kernel/static_call_inline.c src – static call core
arch/x86/kernel/static_call.c src – x86 static call patching
arch/x86/include/asm/alternative.h src – runtime instruction patching
arch/x86/kernel/alternative.c src – x86 alternatives engine
smp_text_poke_single id – safely patch code on SMP using INT3 breakpoints; used by static keys, static calls, ftrace, kprobes
smp_text_poke_batch_add id
smp_text_poke_batch_finish id


๐Ÿ‘ Examples

housekeeping_overridden id
preempt_schedule id
tracepoints


๐Ÿ“– References

Static Keys doc
x86 CPU feature flags doc


Memory barriers (MB) are synchronization mechanisms used to ensure proper ordering of memory operations in a SMP environment. They play a crucial role in maintaining the consistency and correctness of data shared among different CPU cores or processors. MBs prevent unexpected and potentially harmful reordering of memory access instructions by the compiler or CPU, which can lead to data corruption and race conditions in a concurrent software system.

โšฒ API

man 2 membarrier
asm-generic/barrier.h inc
mb id, rmb id, wmb id
smp_mb id, smp_rmb id, smp_wmb id


โš™๏ธ Internals

arch/x86/include/asm/barrier.h src – x86 memory barrier instructions
kernel/sched/membarrier.c src – membarrier system call


๐Ÿ“– References

Memory barriers doc


States

[edit | edit source]

C-states and P-states are features in modern CPUs designed to improve energy efficiency.

๐Ÿ—๏ธ Acronyms

C-states – CPU(?) states, aka idle states
EPP – Energy Performance Preference doc
HWP – hardware-managed P-states, see hwp_only
P-states – Performance states, see CPU Power and frequency scaling


โšฒ API

cpupower


๐Ÿ“– References

Working-State Power Management doc
https://lwn.net/Kernel/Index/#Power_management


C-states, power states:

C0 โ€“ operating, executing instructions.
C1 (Halt) โ€“ internal clocks stopped.
C1E (Enhanced Halt) โ€“ clocks stopped, voltage and frequency reduced.
C2 (Stop-Clock) โ€“ internal and external clocks stopped.
C3 (Deep Sleep) โ€“ clocks stopped, L1/L2 cache may flush, local APIC timer stops, requiring tick broadcast.
C4 (Deeper Sleep) โ€“ voltage reduced.
C6 (Deep Power Down) โ€“ state saved to SRAM, voltage can drop to 0V.
C7 (Deeper Power Down) โ€“ C6 + L3 cache flushed.
Modern Intel typically uses C1/C1E and C6, skipping C2โ€“C5.
โš ๏ธ ACPI state names (C1_ACPI, C2_ACPI, C3_ACPI) may not match actual hardware C-states. The MWAIT hint reveals the real state: e.g. MWAIT 0x60 = hardware C6 may appear as "C3_ACPI".


โšฒ API

turbostat --show CPU --quiet -n 1 --interval 0.1 --show sysfs
idle=
/dev/cpu_dma_latency – see set_cpu_dma_latency id
C-states interfaces:
cpupower idle-info โ€“ show driver, governor, states with latency and residency
/sys/devices/system/cpu/cpuidle/
/sys/devices/system/cpu/cpu*/cpuidle/
cat /sys/devices/system/cpu/cpu0/cpuidle/state*/name โ€“ list available C-states
linux/cpuidle.h inc โ€“ generic framework for CPU idle power management
linux/pm_qos.h inc


โš™๏ธ Internals

drivers/cpuidle src โ€“ CPU idle governors and drivers
drivers/idle/intel_idle.c src โ€“ intel_idle doc, hardcoded C-states per CPU model, modern Intel (C1/C1E/C6)
drivers/acpi/processor_idle.c src โ€“ acpi_idle, reads C-states from ACPI tables, generic fallback (C1/C2/C3)
kernel/power/qos.c src โ€“ PM quality of service
cpu_latency_qos_miscdev id โ€“ implementation of /dev/cpu_dma_latency


๐Ÿ“– References

CPU Idle Time Management doc
Intel C-states reference
HPE C-states reference


๐Ÿ“š Further reading

https://lwn.net/Kernel/Index/#Power_management-cpuidle
PM Quality Of Service Interface doc

Power and frequency

[edit | edit source]

P-states, performance states:

P0 – maximum power and frequency
Pn – less power and frequency
...


โšฒ API

Reliable measurement of actual CPU frequency
turbostat --quiet --show CPU,Bzy_MHz -n 1 --interval 0.1
Bzy_MHz – average clock rate while the CPU was not idle (ie. in "c0" state).
intel_pstate=
Kernel Command Line Options for intel_pstate doc
cpufreq.default_governor=
P-states interfaces:
/sys/devices/system/cpu/cpufreq/
/sys/devices/system/cpu/cpu*/cpufreq/
scaling_cur_freq – unreliable assumption on CPU frequency
/sys/devices/system/cpu/intel_pstate/
linux/cpufreq.h inc
rust/kernel/cpufreq.rs src โ€“ Rust bindings
linux/sched/cpufreq.h inc – interface between cpufreq drivers and the scheduler


โš™๏ธ Internals

drivers/cpufreq src – CPU frequency scaling drivers
intel_pstate id
acpi_cpufreq_driver id
kernel/sched/cpufreq_schedutil.c src – implementation of cpufreq.default_governor=schedutil
arch/x86/kernel/cpu/intel_epb.c src – Intel Performance and Energy Bias Hint support


๐Ÿ“– References

CPU Performance Scaling doc
Device Frequency Scaling doc
CPUFreq Governor
CPUFreq - CPU frequency and voltage scaling doc
Intel Performance and Energy Bias Hint doc
intel_pstate CPU Performance Scaling Driver doc
General Information doc
Operation Modes doc
Active Mode doc
Passive Mode doc
Turbo P-states Support doc
Processor Support doc
Support for Hybrid Processors doc
Hybrid Processors with SMT doc
Capacity-Aware Scheduling Support doc
Energy-Aware Scheduling Support doc
User Space Interface in sysfs doc
Global Attributes doc
Interpretation of Policy Attributes doc
Coordination of P-State Limits doc
Energy vs Performance Hints doc
intel_pstate vs acpi-cpufreq doc
Kernel Command Line Options for intel_pstate doc
Diagnostics and Tuning doc
Trace Events doc
ftrace doc


๐Ÿ“š Further reading

https://lwn.net/Kernel/Index/#Power_management-Frequency_scaling
CPU frequency scaling
cpufreq ltp
How to use cpufrequtils
cpufreq-info
cpufreq-set
https://github.com/intel/power-optimization-library
https://github.com/intel/kubernetes-power-manager


Architectures

[edit | edit source]

Linux CPU architectures refer to the different types of central processing units (CPUs) that are compatible with the Linux operating system. Linux is designed to run on a wide range of CPU architectures, which allows it to be utilized on various devices, from smartphones to servers and supercomputers. Each architecture has its own unique features, advantages, and design considerations.

Architectures are classified by family (e.g. x86, ARM), word or long int size (e.g. CONFIG_32BIT id, CONFIG_64BIT id).


Some functions with different implementations for different CPU architectures:

do_boot_cpu id > start_secondary id > cpu_init id
setup_arch id, start_thread id, get_current id, current id

โšฒ API

BITS_PER_LONG id, __BITS_PER_LONG id,

โš™๏ธ Internals

arch src – architecture-specific code

๐Ÿ“– References

CPU Architectures doc
CONFIG_X86 id
arch/x86 src – x86 architecture support
arch/x86/kernel src – core (SMP boot, traps, IRQ, TSC, reboot), x86 Topology doc
arch/x86/kernel/apic src – APIC (local APIC, I/O APIC, IPI delivery)
arch/x86/kernel/cpu/bugs.c src – CPU vulnerability mitigations, see Security
arch/x86/kernel/cpu/mce src – Machine-check exception handling
arch/x86/kernel/cpu/microcode src – The Linux Microcode Loader doc
arch/x86/kernel/cpu/mtrr src – MTRR driver
arch/x86/mm src – TLB, PAT, MTRR, SME, see Memory
arch/x86/entry src – syscall and interrupt entry points, see Syscalls
arch/x86/boot src – boot protocol and early setup, x86 Feature Flags doc, see Booting
arch/x86/kvm src – KVM, see Virtualization
arch/x86/crypto src – AES-NI, SHA, CRC, see Crypto
arch/x86/coco src – confidential computing (TDX, SEV)
arch/x86/events src – PMU drivers for perf, see Perf
arch/x86/net src – x86 BPF JIT compiler, see eBPF
arch/x86/xen src – Xen paravirtualization
arch/x86/hyperv src – Hyper-V support
drivers/platform/x86 src – x86 platform drivers
man 1 perf-intel-pt – support for Intel Processor Trace within perf
CPU feature flags
[edit | edit source]

CPU features detected at boot from CPUID, visible in /proc/cpuinfo flags.

arch/x86/include/asm/cpufeatures.h src
arch/x86/include/generated/asm/cpufeaturemasks.h src
man 4 cpuid – x86 CPUID device
tools/arch/x86/kcpuid src – kernel CPUID dumping tool
cd tools/arch/x86/kcpuid && make && ./kcpuid --detail | grep $'^\t' – list local CPU features with descriptions
https://gitlab.com/x86-cpuid.org/x86-cpuid-db – CPUID feature database

Extended features (newest first):

Compute:

AMX – Advanced Matrix Extensions for AI/ML workloads, 2023
AVX-512 – 512-bit SIMD, 2016

Security:

X86_FEATURE_SHSTK id – CET Shadow Stack, control-flow integrity, 2020
X86_FEATURE_IBT id – CET Indirect Branch Tracking, 2020
X86_FEATURE_UMIP id – User-Mode Instruction Prevention, 2017
X86_FEATURE_PKU id – Memory Protection Keys for user pages, 2016

Memory management:

X86_FEATURE_LA57 id – 5-level paging, 57-bit virtual addresses (128 PB), 2019

Timing:

X86_FEATURE_ART id – Always Running Timer, fixed TSC/crystal ratio for PTP, 2016
X86_FEATURE_TSC_DEADLINE_TIMER id – APIC timer in TSC-deadline mode, 2011

Virtualization:

X86_FEATURE_FRED id – Flexible Return and Event Delivery, replaces IDT, 2025

Additional baseline not in microarchitecture levels but present on all post-2017 CPUs:

adx – multi-precision arithmetic
aes – hardware AES acceleration
apic – APIC on-chip
clflush – CLFLUSH instruction
clflushopt – optimized cache line flush
constant_tsc – TSC ticks at constant rate across P-states and C-states
de – Debugging Extensions
fsgsbase – direct FS/GS base access from userspace
ht – Hyper-threading
invpcid – selective PCID TLB invalidation
mca – Machine Check Architecture
mce – Machine-check exception
msr – Model-Specific Registers (RDMSR/WRMSR)
mtrr – Memory Type Range Registers
nonstop_tsc – TSC does not stop in C-states
nx – No-execute page protection
pat – Page attribute table
pcid – avoids full TLB flush on context switch
pse36 – Page Size Extension (36-bit)
rdrand – hardware random number generator
rdseed – hardware random seed
rdtscp – RDTSCP instruction
sep – SYSENTER/SYSEXIT
smap – blocks kernel accessing user pages
smep – blocks kernel executing user pages
tsc – Time Stamp Counter
x2apic – extended APIC, supports >256 CPUs
x86-64-v4 – AVX-512, ~2017
x86-64-v3 – AVX/AVX2, FMA, BMI, ~2015
x86-64-v2 – SSE3/SSSE3/SSE4, POPCNT, ~2009
x86-64-v1 – SSE/SSE2, required by kernel

Can be disabled at compile time:

CENTAUR_MCR, CYRIX_ARR, ENQCMD, FRED, K6_MTRR, LAM, SEV_SNP, SGX, TDX_GUEST, USER_SHSTK, VME, XENPV
VMX / SVM – hardware virtualization, 2005/2006

๐Ÿ“– References

x86-specific doc
x86_64 Support doc
architecture-specific initialization
https://lwn.net/Kernel/Index/#Architectures-x86
CONFIG_ARM id – 32-bit, CONFIG_ARM64 id – 64-bit (AArch64)
arch/arm src – 32-bit ARM
arch/arm64 src – 64-bit ARM (AArch64)
ARM big.LITTLE – heterogeneous multiprocessing, see EAS

๐Ÿ“– References

ARM Architecture doc
ARM64 Architecture doc
Memory Tagging Extension (MTE) doc – hardware memory safety
Scalable Vector Extension (SVE) doc
https://lwn.net/Kernel/Index/#Architectures-ARM
  1. โ†‘ Malte Skarupke. "Measuring Mutexes, Spinlocks and how Bad the Linux Scheduler Really is".