rust: atomic: add `fetch_sub` and update docs
Subsystems (3)
Andreas Hindborg
reviewerv2 cover rust: atomic: add `fetch_sub` and update docs
Add fetch_sub and improve documentation of fetch_add.
---
Changes in v2:
- Update example to be more clear.
- Add a patch that updates documentation for fetch_add.
- Link to v1: https://lore.kernel.org/r/[email protected]
---
Andreas Hindborg (2):
rust: atomic: add fetch_sub
rust: atomic: update documentation for fetch_add
rust/kernel/sync/atomic.rs | 52 +++++++++++++++++++++++++++++++++---- rust/kernel/sync/atomic/internal.rs | 5 ++++ 2 files changed, 52 insertions(+), 5 deletions(-)
---
base-commit: 63804fed149a6750ffd28610c5c1c98cce6bd377
change-id: 20260128-atomic-sub-2ff15962df12
Best regards,
Signature · 1 line
Andreas Hindborg <[email protected]>
Andreas Hindborg
reviewerPATCH v2 1/2 rust: atomic: add fetch_sub
Add Atomic::fetch_sub with implementation and documentation in line with existing Atomic::fetch_add implementation.
--- rust/kernel/sync/atomic.rs | 43 +++++++++++++++++++++++++++++++++++++ rust/kernel/sync/atomic/internal.rs | 5 +++++ 2 files changed, 48 insertions(+)
rust/kernel/sync/atomic.rs +43 -0
@@ -559,4 +559,47 @@ pub fn fetch_add<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering)// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. unsafe {from_repr (ret) } } + +/// Atomic fetch and subtract. +/// +/// Atomically updates `*self` to `(*self).wrapping_sub(v)`, and returns the value of `*self` +/// before the update. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Acquire)); +/// assert_eq!(30, x.load(Relaxed)); +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Full)); +/// assert_eq!(30, x.load(Relaxed)); +/// ``` +#[inline(always)] +pub fn fetch_sub <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T +where +// Types that support addition also support subtraction. +T :AtomicAdd <Rhs >, + { +let v =T ::rhs_into_delta (v); + +// INVARIANT: `self.0` is a valid `T` after `atomic_fetch_sub*()` due to safety requirement +// of `AtomicAdd`. +let ret = { +match Ordering ::TYPE { +OrderingType ::Full =>T ::Repr ::atomic_fetch_sub (&self.0 , v), +OrderingType ::Acquire =>T ::Repr ::atomic_fetch_sub_acquire (&self.0 , v), +OrderingType ::Release =>T ::Repr ::atomic_fetch_sub_release (&self.0 , v), +OrderingType ::Relaxed =>T ::Repr ::atomic_fetch_sub_relaxed (&self.0 , v), + } + }; + +// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. +unsafe {from_repr (ret) } + } }
rust/kernel/sync/atomic/internal.rs +5 -0
@@ -261,5 +261,10 @@ fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) ->// SAFETY: `a.as_ptr()` is valid and properly aligned. unsafe { bindings::#call(v, a.as_ptr().cast()) } } + + fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { +// SAFETY: `a.as_ptr()` is valid and properly aligned. + unsafe { bindings::#call(v, a.as_ptr().cast()) } + } } );
Signature · 1 line
2.51.2
Re: [PATCH v2 1/2] rust: atomic: add fetch_sub
rust/kernel/sync/atomic/internal.rs fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> · line 268
Quoted 5 lines · Andreas Hindborg
rust/kernel/sync/atomic/internal.rs +4
-0+ fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { +// SAFETY: `a.as_ptr()` is valid and properly aligned. + unsafe { bindings::#call(v, a.as_ptr().cast()) } + }
[ I see fetch_add does the same, so it is fine here in this patch for consistency, but I thought I would leave a note here anyway... ]
The safety comment, as written, could be read as just saying something it is true without justifying it. Something like:
a.as_ptr() guarantees the returned pointer is valid and properly aligned.
would show better why it is such, rather than simply stating it.
Cheers,
Miguel
Andreas Hindborg
reviewerRe: [PATCH v2 1/2] rust: atomic: add fetch_sub
Quoted 7 lines · Miguel Ojeda
rust/kernel/sync/atomic/internal.rs fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> · line 268
Quoted 5 lines · Andreas Hindborg
rust/kernel/sync/atomic/internal.rs +4
-0+ fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { +// SAFETY: `a.as_ptr()` is valid and properly aligned. + unsafe { bindings::#call(v, a.as_ptr().cast()) } + }
Quoted 7 lines
[ I see
fetch_adddoes the same, so it is fine here in this patch for consistency, but I thought I would leave a note here anyway... ]The safety comment, as written, could be read as just saying something it is true without justifying it. Something like:
a.as_ptr()guarantees the returned pointer is valid and properly aligned.
I'll respin and fix this, for fetch_add as well. I can take the spurious newline you mentioned on same occasion.
Best regards,
Andreas Hindborg
Andreas Hindborg
reviewerPATCH v2 2/2 rust: atomic: update documentation for `fetch_add`
In reply to Andreas HindborgThe documentation for fetch_add does not indicate that the original value is returned by fetch_add. Update the documentation so this is clear.
--- rust/kernel/sync/atomic.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
rust/kernel/sync/atomic.rs +4 -5
@@ -527,16 +527,15 @@ pub fn add<Rhs>(&self, v: Rhs, _: ordering::Relaxed)/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); -/// -/// assert_eq!(54, { x.fetch_add(12, Acquire); x.load(Relaxed) }); +/// assert_eq!(42, x.fetch_add(12, Acquire)); +/// assert_eq!(54, x.load(Relaxed)); /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_add(12, Full)); +/// assert_eq!(54, x.load(Relaxed)); /// -/// assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } ); /// ``` #[inline(always)] pub fn fetch_add <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T
Signature · 1 line
2.51.2
Re: [PATCH v2 2/2] rust: atomic: update documentation for `fetch_add`
Quoted 4 lines · Andreas Hindborg
The documentation for
fetch_adddoes not indicate that the original value is returned byfetch_add. Update the documentation so this is clear.Signed-off-by Andreas Hindborg <[email protected]>
Re: [PATCH v2 2/2] rust: atomic: update documentation for `fetch_add`
In reply to Andreas Hindborgrust/kernel/sync/atomic.rs pub fn add<Rhs>(&self, v: Rhs, _: ordering::Relaxed) · line 539
Quoted 5 lines · Andreas Hindborg
rust/kernel/sync/atomic.rs +1
-1+/// assert_eq!(54, x.load(Relaxed)); /// -/// assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } ); /// ```
Doesn't this leave an empty line at the end of the example?
Cheers,
Miguel