13.1-4"A": Atomic Instructions — LR/SC and AMOs

Part I Linux boot: required Vol. I (Unprivileged) pp. 67–73 · ~6 min read

  • aq/rl bits
  • reservation set
  • constrained lr/sc loop
  • amo
  • misaligned atomicity granule

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

funct53127aq26rl25rs22420rs11915width1412rd117AMO60AMO fmt
Click a field for its role.

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 — 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.

When must / may an SC fail?
VerdictWhy
Another hart's store to the reservation set observed between LR and SCMUST failThe core mutual-exclusion property.
Another SC executed in between (any address)MUST failAny SC invalidates the reservation
SC address outside the reservation setMUST failThe set was never promised for those bytes.
Device (non-hart) write to the exact bytes the LR accessedMUST failDevices must invalidate on overlap with the LR’d bytes.
Device write elsewhere in the reservation setMAY failLegacy-bus accommodation
No conflict at allMAY still fail (spuriously)Allowed, if eventuality holds
Dotted-underlined cells have explanations — click one.

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 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 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?

5 questions