5.4.16 · D5Memory Hierarchy & Caches

Question bank — Memory consistency models

2,004 words9 min readBack to topic

First, a one-line glossary so every reveal below reads cleanly — nothing here is used before it is named:

Because almost every reveal below reasons off the four program-order pairs, keep this rulebook in view — it is the whole page in one picture:


True or false — justify

TSO preserves Store→Store ordering, so two stores by one core reach every other core in program order.
True. In the table TSO's S→S is ✅, and the mechanism is the FIFO store buffer: stores drain in the order issued, so every observer sees them in that one order. See Store Buffers and Write Buffering.
Under TSO, a core can observe its own store before it becomes globally visible.
True. Via store-forwarding, a later load reads the buffered value directly from the store buffer, so the core sees its own write immediately even though other cores don't yet — this is exactly the S→L (❌) relaxation in action.
Sequential Consistency means each core's memory ops run in a fixed order and that order is fastest.
False. SC fixes the ordering (a single total interleaving respecting each core's program order — all four pairs ✅) but is typically the slowest model precisely because ✅ on S→L forbids the store-buffer bypass that gives real speed.
Coherence and consistency are two names for the same guarantee.
False. Coherence orders writes to one address; consistency (the whole four-pair table) orders ops across different addresses. Coherence is necessary but strictly weaker. See Cache Coherence.
On x86 (TSO) the message-passing flag pattern needs no fence.
True. The producer does two stores (data=42 then flag=1); TSO's S→S is ✅, so data is visible before flag, and any consumer that sees the flag also sees the data. See Memory Barriers and Fences.
A memory fence makes the whole program sequentially consistent.
False. A fence only forces ✅ ordering across its own position (ops before it vs ops after it); everywhere else the weak model's ❌ freedoms still apply. It buys back SC locally, not globally.
If a program has no data races (all shared access is via locks), the weak/relaxed model still lets threads see stale data.
False in effect. Locks embed the necessary fences, converting the relevant ❌ pairs back to ✅ at the lock boundaries, so a race-free program behaves as if SC — the SC-for-DRF guarantee. See Atomic Operations and Locks.
volatile in C/C++ gives cross-thread ordering.
False. volatile only stops the compiler from caching a value in a register; it emits no hardware fences, so every ❌ in the weak-model row stays ❌ across threads. Use atomics from the C++ Memory Model (acquire-release) instead.
Out-of-order execution alone (no store buffer) can produce the Store-Buffering r1==0 && r2==0 outcome.
True. Letting a later load complete before an earlier store drains is an S→L reorder (the ❌ cell), and that alone lets both loads read stale 0. See Out-of-Order Execution.
Under SC, IRIW (two writers, two readers seeing writes in opposite orders) is possible.
False. SC keeps all four pairs ✅ and enforces a single global order of all ops, so all readers agree on the order of the two independent writes.

Spot the error

"TSO reorders L→L, so a core can see its own two loads out of order."
Error: TSO preserves L→L (✅ in the table). The only ❌ in TSO's row is S→L (a store bypassed by a later load). Mnemonic: "Stores Look Late."
"A fence speeds the program up by draining the store buffer."
Error: a fence slows the core — it stalls until the buffer drains. Its purpose is to convert a ❌ pair back to ✅ (correctness); the cost is performance, so you place it only where ordering is needed.
"On ARM, adding a fence only on the producer side fixes message passing."
Error: on ARM all four pairs are ❌, so you need both — a release fence on the producer (forces data=42 visible before flag=1) and an acquire fence on the consumer (forces the flag-read before the data read). One side alone leaves the other's reorder open.
"Coherence guarantees that if Core A writes x then y, Core B sees x before y."
Error: coherence only orders writes to the same address. The cross-address "x then y" question is the S→S pair of the consistency table, not coherence.
"Because x86 is TSO, LOCK-prefixed instructions are unnecessary for atomicity."
Error: TSO governs ordering (the four-pair table), not atomicity of a read-modify-write. A LOCK prefix (or MFENCE) is still needed for atomic increments and to force the S→L cell back to ✅. See Atomic Operations and Locks.
"Program order and visibility order are the same thing on a single core."
Error: even one core can have its store buffered — its own program order stays intact from its viewpoint (store-forwarding), but the global visibility order of that store to other cores is delayed.

Why questions

Why does TSO allow only S→L reordering and not the other three pairs?
Because only stores are buffered. The buffered store lets a later load finish first (S→L → ❌); the FIFO keeps S→S ✅, and non-buffered loads keep L→L and L→S ✅.
Why can't a single core detect that its own store is still buffered?
Store-forwarding: a later load to the same address reads the pending value straight from the buffer, so the core always sees a consistent, in-order view of its own memory.
Why does SC forbid the Store-Buffering double-zero outcome?
Label the ops: S1 = Core 1 writes x=1, L2 = Core 1 reads y; S3 = Core 2 writes y=1, L4 = Core 2 reads x. The bad outcome r1==0 means L2 read y before S3 wrote it, i.e. L2 < S3 in the global order; r2==0 means L4 < S1. Program order adds S1 < L2 and S3 < L4. Chaining gives S1 < L2 < S3 < L4 < S1 — a cycle, which no single total order can contain. Hence SC forbids it.
Why do weak models exist at all if they're so error-prone?
They keep almost every ❌ open so ordinary memory ops run reordered and fast; the programmer inserts fences only at the handful of synchronization points (locks, flags) that actually need ✅, trading a little effort for large speedups on many-core hardware.
Why is IRIW possible on POWER/ARM but not on TSO?
Those models are non-multi-copy-atomic (defined above): a store can reach different cores at different times, so two readers may observe two writes in opposite orders. TSO is multi-copy-atomic with a single total store order, forbidding it.
Why does a fence "buy back" SC only locally?
A fence forces ✅ only for pairs straddling its position (before → after); it says nothing about ops far from it, so unfenced regions keep the weak model's ❌ freedoms.

Edge cases

If only one core touches memory (no sharing), does the consistency model matter?
No. With no other observer, program order is preserved from that core's own view via store-forwarding — every reorder is invisible, so all rows of the table look identical.
What happens under any model if two ops are to the same address?
Coherence takes over: all cores agree on a single order of writes to that one address, regardless of how weak the consistency model's four-pair row is.
Two stores to different addresses on ARM with no fence — what's the weakest legal observation?
Another core may see them in either order (S→S is ❌ on ARM), including seeing the second store's effect while the first is still not visible.
A load followed by a store to a different address on TSO — can they reorder?
No. L→S is ✅ on TSO (only S→L is ❌), so the load is globally ordered before the store.
Does a fence between two stores help on x86?
For S→S ordering it's redundant (TSO already has that cell ✅), but it does drain the buffer and force the surrounding S→L cell back to ✅ — so it's not a no-op, just not needed for the S→S guarantee.
If a program is fully fenced between every pair of ops, which model does it emulate?
SC. Fencing every boundary forces every ❌ back to ✅, recovering a single total order — at maximum performance cost.
What if the store buffer is empty when a fence executes?
The fence still enforces ordering semantically, but has near-zero cost since there is nothing to drain — the stall is proportional to the number of pending stores.

Recall One-line self-check before you leave

Name TSO's single relaxed cell, the model property that permits IRIW, and the one thing volatile does not give you. Answer ::: S→L (the one ❌ in TSO's row); non-multi-copy-atomicity (POWER/ARM); cross-thread ordering.