From b6f6387a33e64828bd758f39c79da3915f853893 Mon Sep 17 00:00:00 2001 From: Matthieu M Date: Sun, 19 Oct 2025 17:12:53 +0200 Subject: [PATCH 1/2] Improve the documentation of atomic::fence Attempt to "fix" two flaws of the current documentation: 1. The over-emphasis of fence - fence synchronization, relegating atomic - fence and fence - atomic synchronization to second fiddle. 2. The lack of explanation as to how to properly perform atomic - fence and fence - atomic synchronization. It does so by first making it clear that there are 3 different ways to use an atomic fence, then presenting a full example for each usecase, noting the particular position of the fence with regard to the atomic operation, and rounding up with generic notes. --- library/core/src/sync/atomic.rs | 74 ++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 30a42d4eb5e64..00e90c7a659e6 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -4277,11 +4277,61 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of /// memory operations around it. /// -/// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes -/// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there -/// exist operations X and Y, both operating on some atomic object 'm' such -/// that A is sequenced before X, Y is sequenced before B and Y observes -/// the change to m. This provides a happens-before dependence between A and B. +/// There are 3 different ways to use an atomic fence: +/// +/// - atomic - fence synchronization: an atomic operation with (at least) [`Release`] ordering +/// semantics synchronizes with a fence with (at least) [`Acquire`] ordering semantics. +/// - fence - atomic synchronization: a fence with (at least) [`Release`] ordering semantics +/// synchronizes with an atomic operation with (at least) [`Acquire`] ordering semantics. +/// - fence - fence synchronization: a fence with (at least) [`Release`] ordering semantics +/// synchronizes with a fence with (at least) [`Acquire`] ordering semantics. +/// +/// These 3 ways complement the regular atomic - atomic synchronization. +/// +/// ## Atomic - Fence +/// +/// An atomic operation 'X' with (at least) [`Release`] ordering semantics on some atomic object +/// 'm' on thread 1 is paired on thread 2 with an atomic read 'Y' with any order on 'm' followed by +/// a fence 'B' with (at least) [`Acquire`] ordering semantics. This provides a happens-before +/// dependence between X and B. +/// +/// ```text +/// Thread 1 Thread 2 +/// +/// m.store(3, Release); X --------- +/// | +/// | +/// -------------> Y if m.load(Relaxed) == 3 { +/// B fence(Acquire); +/// ... +/// } +/// ``` +/// +/// ## Fence - Atomic +/// +/// A fence 'A' with (at least) [`Release`] ordering semantics followed by an atomic store 'X' with +/// any ordering on some atomic object 'm' on thread 1 is paired on thread 2 with an atomic +/// operation 'Y' with (at least) [`Acquire`] ordering semantics. This provides a happens-before +/// dependence between A and Y. +/// +/// ```text +/// Thread 1 Thread 2 +/// +/// fence(Release); A +/// m.store(3, Relaxed); X --------- +/// | +/// | +/// -------------> Y if m.load(Acquire) == 3 { +/// ... +/// } +/// ``` +/// +/// ## Fence - Fence +/// +/// A fence 'A' which has (at least) [`Release`] ordering semantics followed by an atomic store 'X' +/// with any ordering on some atomic object 'm' on thread 1 is paired on thread 2 with an atomic +/// operation 'Y' with any ordering on 'm' followed by a fence 'B' with (at least) [`Acquire`] +/// ordering semantics. This provides a happens-before dependence between A and B. /// /// ```text /// Thread 1 Thread 2 @@ -4296,14 +4346,16 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// } /// ``` /// -/// Note that in the example above, it is crucial that the accesses to `m` are atomic. Fences cannot +/// ## Mandatory Atomic +/// +/// Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot /// be used to establish synchronization among non-atomic accesses in different threads. However, -/// thanks to the happens-before relationship between A and B, any non-atomic accesses that -/// happen-before A are now also properly synchronized with any non-atomic accesses that -/// happen-after B. +/// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic +/// operation or fence with (at least) [`Release`] ordering semantics are now also properly +/// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with +/// (at least) [`Aquire`] ordering semantics. /// -/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize -/// with a fence. +/// ## Memory Ordering /// /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] /// and [`Release`] semantics, participates in the global program order of the From 1b21c0444bcb8b9939cf363eee7d9583b2551806 Mon Sep 17 00:00:00 2001 From: Matthieu M Date: Mon, 20 Oct 2025 18:05:30 +0200 Subject: [PATCH 2/2] Fix typo in Acquire spelling. --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 00e90c7a659e6..53696c599326d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -4353,7 +4353,7 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic /// operation or fence with (at least) [`Release`] ordering semantics are now also properly /// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with -/// (at least) [`Aquire`] ordering semantics. +/// (at least) [`Acquire`] ordering semantics. /// /// ## Memory Ordering ///