Define the generation protocol's memory ordering requirements and remove its deprecated barrier macros

XMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Minor - P4
    • None
    • Affects Version/s: None
    • 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

      1. 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.
      2. Replace the deprecated macros with the sanctioned typed atomics.
      3. Re-derive whether each standalone barrier is still needed once the surrounding accesses carry their own ordering, and delete the ones that are redundant.
      4. 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, :289WT_ACQUIRE_READ_WITH_BARRIER
      • generation.c:362WT_RELEASE_WRITE_WITH_BARRIER (in __wt_session_gen_leave)

      Standalone barriers:

      • generation.c:69WT_RELEASE_BARRIER in __wt_gen_init
      • generation.c:345WT_FULL_BARRIER in the __wt_session_gen_enter publish-and-recheck loop
      • generation.c:365WT_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.

            Assignee:
            [DO NOT USE] Backlog - Storage Engines Team
            Reporter:
            Chenhao Qu
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: