The A extension is what makes multi-hart Linux possible: atomic read-modify-writes on shared memory, in two flavors — Zalrsc (load-reserved/store-conditional) and Zaamo (fetch-and-op). Both live in R-type encodings under the AMO opcode, and both carry the two ordering bits that implement release consistency (RCsc).
13.1 The aq / rl bits
The bits constrain observation only within the address domain the
atomic touches (memory or I/O) — cross-domain ordering still needs
FENCE. Software rule: don’t set rl alone on LR or aq alone on SC;
those combinations promise nothing stronger than unordered and may just
run slower.
13.2 Zalrsc: reservations, precisely
LR.W/D loads, sign-extends into rd (W on RV64), and registers a
reservation set reservation set Bytes registered by LR (superset of the addressed word/doubleword). SC succeeds only if the reservation is valid, covers the written bytes, and no conflicting store/SC intervened. One reservation per hart; ANY SC invalidates it.
defined in ch. I·13 — open in glossary
— implementation-chosen,
but covering at least the addressed word. SC.W/D writes rs2 only if
the reservation is still valid and covers the bytes being written;
success writes 0 to rd, failure a nonzero code and no memory write.
| Verdict | Why | |
|---|---|---|
| Another hart's store to the reservation set observed between LR and SC | MUST fail | The core mutual-exclusion property. |
| Another SC executed in between (any address) | MUST fail | Any SC invalidates the reservation |
| SC address outside the reservation set | MUST fail | The set was never promised for those bytes. |
| Device (non-hart) write to the exact bytes the LR accessed | MUST fail | Devices must invalidate on overlap with the LR’d bytes. |
| Device write elsewhere in the reservation set | MAY fail | Legacy-bus accommodation |
| No conflict at all | MAY still fail (spuriously) | Allowed, if eventuality holds |
Details with teeth: LR/SC require natural alignment (misaligned → address-misaligned or access-fault; emulation is explicitly impractical — it could straddle two reservation sets). A failed SC may be treated as a store for protection purposes, and whether it sets page-table D bits is UNSPECIFIED. An SC can never be observed by another hart before its LR. On a context switch, the kernel executes an SC to a scratch word to kill any stale reservation.
13.3 Constrained loops: the forward-progress contract
A constrained LR/SC loop constrained lr/sc loop A <=16-instruction sequential loop (LR..SC with only restricted base-I instructions between; retry branches allowed) in a region with the eventuality property. The EE must guarantee livelock freedom for it; unconstrained sequences may never succeed. defined in ch. I·13 — open in glossary is the shape that earns the architectural guarantee:
- at most 16 instructions, placed sequentially in memory;
- between LR and SC: only base-I instructions, excluding loads, stores, backward jumps, taken backward branches, JALR, FENCE, SYSTEM (compressed Zca/Zcb forms of the allowed set are fine);
- the retry path may branch backward to repeat the sequence;
- LR/SC address in a region with the eventuality property (the EE says which regions qualify);
- SC to the same address and size as the latest LR.
For such loops the environment guarantees something eventually happens: a successful SC to that reservation set (by this or another hart), an unconditional store/AMO or device write to it, an exit branch, or a trap. That is livelock freedom, not starvation freedom — a deliberate weakening (sufficient for C11/C++11, much easier to build). Everything else is unconstrained: implementations may fail it forever, and portable software must carry a fallback. One more obligation flows to the memory system: other harts’ loads and LRs — including the cache evictions and speculative misses they cause — must not impede progress indefinitely, which in practice means reservations are tracked independently of shared-cache line residency.
13.4 Zaamo: fetch-and-op
Nine operations — AMOSWAP, AMOADD, AMOAND, AMOOR, AMOXOR,
AMOMAX[U], AMOMIN[U], in .W/.D — each atomically: load old value
→ rd, compute op(old, rs2), store back. RV64 .W AMOs sign-extend rd and
ignore the upper half of rs2. Natural alignment required — unless the
platform’s misaligned atomicity
granule misaligned atomicity granule Optional PMA (Vol II): a power-of-two granule within which misaligned AMOs/loads/stores (base + F/D/Q <=XLEN) raise no alignment exception and execute as ONE RVWMO memory operation.
defined in ch. I·13 — open in glossary
PMA (Vol II) covers all accessed bytes, in which case the
access raises no alignment exception and counts as a single RVWMO
memory operation.
AMOs scale where LR/SC spins: they can execute at shared cache banks or memory controllers (“far atomics”), and when rd = x0 the old-value fetch can be elided — the parallel-reduction idiom. The canonical spinlock (Listing 3):
li t0, 1 # swap value
again: lw t1, (a0) # test (cheap, no bus traffic)
bnez t1, again
amoswap.w.aq t1, t0, (a0) # test-and-set, acquire
bnez t1, again
# ... critical section ...
amoswap.w.rl x0, x0, (a0) # release by storing 0
aq on the acquiring swap orders the critical section after lock
acquisition; rl on the releasing swap orders it before release —
nothing more (a FENCE pair would over-order). The AMO-swap idiom for
both acquire and release is also what speculative lock elision wants to
pattern-match.
Hardware Designer Notes
The classic single-core simplification: with one hart and no DMA observers, a reservation is just a flag + address register cleared on SC or trap. Multi-hart is where the two hard obligations land — eviction- independent reservation tracking, and the eventuality guarantee. The cheapest credible strategy for the latter: after LR, hold the line exclusively for a bounded number of cycles (small, fixed), refusing snoops; that window bounds constrained loops (≤16 instructions, no memory ops inside) and converts livelock into bounded retry. The precise formal statement of what a successful LR/SC pair means is the Atomicity Axiom of RVWMO — ch. 18 makes it exact.
Minimal Linux-boot hart MUST
- Track reservations independently of cache-line residency — other harts’ loads/evictions/speculation must not indefinitely kill your SCs
- Invalidate the reservation on EVERY SC, failed ones included
- Deliver the livelock-freedom guarantee for constrained loops (e.g. bounded exclusive-hold window after LR)
- Trap misaligned LR/SC/AMOs (address-misaligned or access-fault) unless your misaligned-atomicity-granule PMA covers the access
- Wire aq/rl into the LSU ordering logic, scoped to the accessed domain
MAY simplify / trap-and-emulate
- Implement AMOs internally as LR/SC microsequences — if completion is guaranteed
- Execute AMOs at the L2/memory controller and elide the read when rd=x0
- Fail unconstrained LR/SC sequences unconditionally
- Return failure code 1 through the existing SLT/SLTU result mux — that is why code 1 exists
Check yourself — atomics
1.An SC.W fails. What did it just do to this hart's reservation?
2.Which loop earns the architectural eventual-success (livelock-freedom) guarantee?
3.Why does Listing 3's spinlock use amoswap.w.aq to acquire and amoswap.w.rl to release?
4.A DMA device writes bytes inside a hart's reservation set, but NOT the bytes the LR actually accessed. Must the SC fail?
5.AMOADD.W executes on RV64 with rd=x0. What may a clever implementation skip?