-
Type:
Improvement
-
Resolution: Unresolved
-
Priority:
Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: Reconciliation, Transactions
-
None
-
Storage Engines - Transactions
-
245.241
-
None
-
None
Background
The generation manager (src/support/generation.c, src/include/generation_inline.h) currently mixes three styles of synchronisation:
- typed atomics carrying explicit ordering (_wt_atomic_load_uint64_v_acquire, _wt_atomic_store_uint64_v_relaxed, ...),
- the deprecated WT_ACQUIRE_READ_WITH_BARRIER / WT_RELEASE_WRITE_WITH_BARRIER macros,
- standalone barriers (WT_FULL_BARRIER, WT_RELEASE_BARRIER).
src/include/hardware.h marks both *_WITH_BARRIER macros as deprecated. Standalone barriers are additionally invisible to TSAN — hardware.h says so explicitly, which is why the deprecated macros have a separate TSAN_BUILD definition — so any invariant resting on a bare barrier is unverified by the TSAN variants.
Nine resources now share this single mechanism (WT_GEN_CHECKPOINT, EVICT, HAS_SNAPSHOT, HAZARD, SPLIT, TXN_COMMIT, HAS_CKPT_SNAPSHOT, DISAGG_CKPT, DISAGG_ROLE), with roughly 31 _wt_gen() call sites, 22 wt_session_gen(), 6 wt_session_gen_enter() and 8 _wt_session_gen_leave(). Each resource has its own reason for reading a generation, and no single document states what ordering each one actually needs.
WT-18156 made this concrete: it added the two disaggregated slots and made __wt_gen() an acquire load for every caller, because the disaggregated protocol needs the generation read ordered after another shared variable loaded before it. Whether the other seven resources need that ordering was not analysed — acquire was chosen as the conservative option, and the choice was questioned in review on PR #14304.
Scope
- Document, per resource, what its generation is ordered against and why: which loads/stores must not be reordered across the generation access, and which of the drain, oldest-generation and enter/leave paths depend on it.
- Replace the deprecated macros with the sanctioned typed atomics.
- Re-derive whether each standalone barrier is still needed once the surrounding accesses carry their own ordering, and delete the ones that are redundant.
- Decide whether __wt_gen() should keep acquire ordering for all callers, or whether the ordering belongs at the call sites that need it.
Sites
Deprecated macros:
- generation.c:108, :239, :267, :289 — WT_ACQUIRE_READ_WITH_BARRIER
- generation.c:362 — WT_RELEASE_WRITE_WITH_BARRIER (in __wt_session_gen_leave)
Standalone barriers:
- generation.c:69 — WT_RELEASE_BARRIER in __wt_gen_init
- generation.c:345 — WT_FULL_BARRIER in the __wt_session_gen_enter publish-and-recheck loop
- generation.c:365 — WT_FULL_BARRIER in __wt_session_gen_leave
Note on the replacement macros
The deprecation notes in hardware.h say to use WT_RELEASE_WRITE / WT_ACQUIRE_READ instead, but no such public macro exists. gcc.h defines ACQUIRE_READ / RELEASE_WRITE and documents them as internal to that header ("For all other cases, please use _wt_atomic_store<type>release(...)"), so the sanctioned form is the typed wt_atomicacquire / wt_atomic_release helpers. The deprecation notes should be corrected to point at those.
Risk
The publish, full barrier and recheck loop in __wt_session_gen_enter is load-bearing for both the drain and oldest-generation scans, and since WT-18156 it also pairs with a disaggregated checkpoint delivery's generation advance. Changes there need the reasoning written down rather than a mechanical macro substitution.