OpenJDK Trivia: Volatile Access on RISC-V
§1. JMM and C2
Volatile writes have release semantics; volatile reads have acquire semantics. Volatile accesses also participate in a total synchronization order consistent with program order. Release/acquire alone is therefore insufficient: a volatile write followed by a volatile read needs StoreLoad ordering.
BarrierSetC2::load_at() and BarrierSetC2::store_at() use C2AccessFence in barrierSetC2.cpp to insert these Ideal nodes for multi-copy-atomic targets (x64, AArch64, and RISC-V):
| Access | C2 Ideal sequence |
|---|---|
| Volatile read | LoadMemBarAcquire |
| Volatile write | MemBarReleaseStoreMemBarVolatile |
| Seq-cst CAS | MemBarReleaseCAS (LoadStore)MemBarAcquire |
On PPC64, C2 instead uses a leading MemBarVolatile for volatile reads and seq-cst CAS, and omits the trailing one after volatile stores.
These nodes express ordering requirements. Instruction selection can satisfy them with fences, instruction ordering bits, or the target memory model.
§2. RISC-V code generation
Representative 32-bit accesses. Operands and CAS comparison/retry branches are omitted; + separates instructions.
| Access | RVWMO | RVWMO + Zalasr | Ztso | Ztso + Zalasr |
|---|---|---|---|---|
| Plain load | lw |
lw |
lw |
lw |
| Plain store | sw |
sw |
sw |
sw |
| Volatile load | lw + fence r, rw |
lw.aq |
lw |
lw.aq |
| Volatile store | fence rw, w + sw + fence w, r |
sw.rl |
sw + fence w, r |
sw.rl |
| Seq-cst CAS (LR/SC) | lr.w.aq + sc.w.aqrl |
lr.w.aq + sc.w.rl |
lr.w.aq + sc.w.aqrl |
lr.w.aq + sc.w.rl |
| Seq-cst CAS (Zacas) | amocas.w.aqrl |
amocas.w.aqrl |
amocas.w.aqrl |
amocas.w.aqrl |
- RVWMO needs explicit acquire, release, and StoreLoad fences for ordinary loads/stores used as volatile accesses.
- Zalasr carries ordering in
lw.aq/sw.rl, allowing HotSpot to omit those fences. - Ztso makes acquire/release fences unnecessary, but still permits StoreLoad reordering, so
fence w, rremains after a volatile store.