A full fence orders everything before it against everything after it. Lighter primitives order one direction or one access class.
ISA | Full fence | One-way primitives | Notes |
|---|---|---|---|
x86-TSO | MFENCE | LFENCE, SFENCE order loads or stores only | LOCK-prefixed ops and XCHG carry full barrier semantics. |
ARMv8 | DMB with domain and type | LDAR acquire, STLR release | DSB is stronger (drains and completes); ISB flushes the instruction stream. |
RISC-V RVWMO | FENCE RW,RW | AMO AQ/RL bits, LR/SC AQ/RL | FENCE.TSO restores TSO-like order; predecessor and successor sets can be narrower. |
SFENCE.VMA is not a memory-model fence. It orders page-table writes against address translation, not data accesses against each other.
Address and data dependencies order the dependent access on ARMv8 and RVWMO. A load that feeds another access's address or data cannot appear after it.
Control dependencies need an explicit barrier. ARMv8 needs an ISB after the branch, RISC-V needs a FENCE, and a bare branch is never enough.
An acquire load orders itself before later accesses, and a release store orders itself after earlier ones. Each is one-way: a prior load can still pass an acquire, and a later store can still pass a release.
That one-way pair is enough for flag publication on cumulative models. Patterns needing both directions at once, such as IRIW shapes, need a full fence.
ISA | Writer (data then flag) | Reader (flag then data) |
|---|---|---|
x86-TSO | plain stores, no fence | plain loads, no fence |
ARMv8 | plain store, then STLR flag | LDAR flag, then plain load |
RISC-V | plain store, FENCE, store flag | load flag, FENCE, load data |
The calculation below is illustrative, not measured. It prices one full fence with stated assumptions.
Fence stall, illustrative assumptions:
pending stores in buffer ......... 8
drain rate ........................ 1 store per cycle
barrier handshake ................. 3 cycles
t_drain = 8 stores / 1 per cycle = 8 cycles
t_fence = 8 + 3 = 11 cycles
at 3 GHz, 1 cycle = 0.333 ns (rounded)
11 cycles x 0.333 ns = 3.67 ns (rounded)
one fence per 20-cycle loop adds 11 / 20 = 55 percentThe drain term scales with buffer occupancy, so a fence after bursty stores costs more. Over-fencing serializes memory-level parallelism that the buffer exists to expose.
The MP weak outcome: the poll sees the flag while the data load still reads stale state. Use STLR with LDAR, or a DMB on both sides.
Hoist the fence out or downgrade to release and acquire at the publication point. A fence drains buffers and stalls issue every time it runs.