Memory Barriers¶
Overview¶
Modern CPUs and compilers may execute or reorder memory accesses differently from the original program order.
Although these optimizations improve performance, they can cause other CPUs or hardware devices to observe memory accesses in an unexpected order.
Memory barriers introduce ordering constraints that guarantee the required visibility between CPUs, shared memory, MMIO registers, and DMA devices.
Why Memory Ordering Matters¶
Program order is the order in which instructions appear in source code.
For example:
The compiler or CPU may make ready visible before data, allowing another CPU to observe:
This is known as a memory ordering problem.
Sources of Reordering¶
Memory reordering may occur at multiple levels.
Compiler Reordering¶
The compiler may reorder memory accesses during optimization while preserving the behavior of a single thread.
Compiler barriers prevent these optimizations.
CPU Reordering¶
Modern processors may execute memory accesses out of program order.
Common reasons include:
- Store Buffer
- Load Buffer
- Out-of-Order Execution
- Speculative Execution
Memory barriers prevent the CPU from exposing these reordered accesses to other observers.
Memory Ordering Model¶
Conceptually, memory barriers define the relationship between program order and the order observed by other CPUs or devices.
Without a memory barrier, visible memory order may differ from program order.
Types of Memory Barriers¶
Memory barriers can be divided into two categories.
Compiler Barrier¶
Prevents compiler optimizations that move memory accesses across the barrier.
Linux API:
barrier()
CPU Memory Barrier¶
Prevents the CPU from making specific memory accesses visible out of order.
Linux APIs include:
mb()rmb()wmb()
For SMP systems:
smp_mb()smp_rmb()smp_wmb()
Acquire and Release Ordering¶
Acquire and Release provide one-way ordering guarantees.
Release:
Acquire:
These operations synchronize producer-consumer communication without requiring a full memory barrier.
MMIO Ordering¶
Memory ordering is required when programming hardware registers.
Typical driver sequence:
The barrier guarantees that the device observes the configuration before receiving the START command.
DMA Ordering¶
DMA engines access normal system memory independently of the CPU.
Typical driver sequence:
Without the write barrier, the device may receive the notification before the descriptor contents become globally visible.
Common Linux Memory Barrier APIs¶
| API | Purpose |
|---|---|
barrier() |
Compiler barrier |
mb() |
Full CPU memory barrier |
rmb() |
Read memory barrier |
wmb() |
Write memory barrier |
smp_mb() |
Full memory barrier for SMP synchronization |
smp_rmb() |
SMP read memory barrier |
smp_wmb() |
SMP write memory barrier |
smp_store_release() |
Publish data using Release ordering |
smp_load_acquire() |
Consume published data using Acquire ordering |
Summary¶
Memory barriers do not change program logic.
Instead, they define when memory accesses are allowed to become visible to other CPUs and hardware devices.
Correct use of memory barriers is essential for:
- CPU-to-CPU synchronization
- Lock-free algorithms
- MMIO register programming
- DMA descriptor publication
- Device driver development