From d417c1f6bd6d903a10e18b2ecea8c23bdc481807 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Thu, 17 Apr 2025 23:59:24 +0530 Subject: [PATCH 1/3] Update documentation of `as_ptr` to reflect that its usage must not lead to data races. --- library/core/src/sync/atomic.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 9b1b13e7129ee..f83a69a7901f4 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -3401,12 +3401,8 @@ macro_rules! atomic_int { /// Doing non-atomic reads and writes on the resulting integer can be a data race. /// This method is mostly useful for FFI, where the function signature may use #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")] - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction: operations on it must be atomic. + /// All modifications of an atomic change the value through a shared reference, and can do so safely + /// as long as they use atomic operations. /// /// # Examples /// @@ -3420,7 +3416,7 @@ macro_rules! atomic_int { /// #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] /// - /// // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// // SAFETY: `my_atomic_op` only uses atomic operations so it will not lead to a data race. /// unsafe { /// my_atomic_op(atomic.as_ptr()); /// } From a87f6ea139004893296a05605b9690e33db2dc14 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Fri, 18 Apr 2025 00:19:22 +0530 Subject: [PATCH 2/3] Update documentation of AtomicPtr and AtomicBool to clarify the circumstances of usage --- library/core/src/sync/atomic.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index f83a69a7901f4..d6aaf6fa626b1 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1115,13 +1115,8 @@ impl AtomicBool { /// /// Doing non-atomic reads and writes on the resulting boolean can be a data race. /// This method is mostly useful for FFI, where the function signature may use - /// `*mut bool` instead of `&AtomicBool`. - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction: operations on it must be atomic. + /// `*mut bool` instead of `&AtomicBool`. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. /// /// # Examples /// @@ -1134,6 +1129,8 @@ impl AtomicBool { /// } /// /// let mut atomic = AtomicBool::new(true); + /// + /// // SAFETY: `my_atomic_op` only uses atomic operations so it will not lead to a data race. /// unsafe { /// my_atomic_op(atomic.as_ptr()); /// } @@ -2308,13 +2305,8 @@ impl AtomicPtr { /// /// Doing non-atomic reads and writes on the resulting pointer can be a data race. /// This method is mostly useful for FFI, where the function signature may use - /// `*mut *mut T` instead of `&AtomicPtr`. - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same - /// restriction: operations on it must be atomic. + /// `*mut *mut T` instead of `&AtomicPtr`. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. /// /// # Examples /// From 24152822922b8db8dd8543abde2821d29f3e4df7 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Tue, 22 Apr 2025 20:50:15 +0530 Subject: [PATCH 3/3] Adding intradoc links for better clarity on memory model --- library/core/src/sync/atomic.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index d6aaf6fa626b1..7afd3f8097533 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1113,7 +1113,9 @@ impl AtomicBool { /// Returns a mutable pointer to the underlying [`bool`]. /// - /// Doing non-atomic reads and writes on the resulting boolean can be a data race. + /// Note that doing non-atomic reads or writes on the resulting integer can be + /// Undefined Behavior due to a data race; see the [memory model section] for further information. + /// /// This method is mostly useful for FFI, where the function signature may use /// `*mut bool` instead of `&AtomicBool`. All modifications of an atomic change the value /// through a shared reference, and can do so safely as long as they use atomic operations. @@ -1136,6 +1138,7 @@ impl AtomicBool { /// } /// # } /// ``` + /// [memory model section]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] @@ -2303,7 +2306,9 @@ impl AtomicPtr { /// Returns a mutable pointer to the underlying pointer. /// - /// Doing non-atomic reads and writes on the resulting pointer can be a data race. + /// Note that doing non-atomic reads or writes on the resulting integer can be + /// Undefined Behavior due to a data race; see the [memory model section] for further information. + /// /// This method is mostly useful for FFI, where the function signature may use /// `*mut *mut T` instead of `&AtomicPtr`. All modifications of an atomic change the value /// through a shared reference, and can do so safely as long as they use atomic operations. @@ -2325,6 +2330,7 @@ impl AtomicPtr { /// my_atomic_op(atomic.as_ptr()); /// } /// ``` + /// [memory model section]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] @@ -3390,7 +3396,9 @@ macro_rules! atomic_int { /// Returns a mutable pointer to the underlying integer. /// - /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// Note that doing non-atomic reads or writes on the resulting integer can be + /// Undefined Behavior due to a data race; see the [memory model section] for further information. + /// /// This method is mostly useful for FFI, where the function signature may use #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")] /// All modifications of an atomic change the value through a shared reference, and can do so safely @@ -3414,6 +3422,7 @@ macro_rules! atomic_int { /// } /// # } /// ``` + /// [memory model section]: self#memory-model-for-atomic-accesses #[inline] #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]