Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: sync: atomic: Add fetch_sub()

Add `Atomic::fetch_sub()` with implementation and documentation in line
with existing `Atomic::fetch_add()` implementation.

Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20260220-atomic-sub-v3-1-e63cbed1d2aa@kernel.org
Link: https://patch.msgid.link/20260303201701.12204-12-boqun@kernel.org

authored by

Andreas Hindborg and committed by
Peter Zijlstra
c49cf341 e2f9c86f

+48
+43
rust/kernel/sync/atomic.rs
··· 577 577 // SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. 578 578 unsafe { from_repr(ret) } 579 579 } 580 + 581 + /// Atomic fetch and subtract. 582 + /// 583 + /// Atomically updates `*self` to `(*self).wrapping_sub(v)`, and returns the value of `*self` 584 + /// before the update. 585 + /// 586 + /// # Examples 587 + /// 588 + /// ``` 589 + /// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; 590 + /// 591 + /// let x = Atomic::new(42); 592 + /// assert_eq!(42, x.load(Relaxed)); 593 + /// assert_eq!(42, x.fetch_sub(12, Acquire)); 594 + /// assert_eq!(30, x.load(Relaxed)); 595 + /// 596 + /// let x = Atomic::new(42); 597 + /// assert_eq!(42, x.load(Relaxed)); 598 + /// assert_eq!(42, x.fetch_sub(12, Full)); 599 + /// assert_eq!(30, x.load(Relaxed)); 600 + /// ``` 601 + #[inline(always)] 602 + pub fn fetch_sub<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering) -> T 603 + where 604 + // Types that support addition also support subtraction. 605 + T: AtomicAdd<Rhs>, 606 + { 607 + let v = T::rhs_into_delta(v); 608 + 609 + // INVARIANT: `self.0` is a valid `T` after `atomic_fetch_sub*()` due to safety requirement 610 + // of `AtomicAdd`. 611 + let ret = { 612 + match Ordering::TYPE { 613 + OrderingType::Full => T::Repr::atomic_fetch_sub(&self.0, v), 614 + OrderingType::Acquire => T::Repr::atomic_fetch_sub_acquire(&self.0, v), 615 + OrderingType::Release => T::Repr::atomic_fetch_sub_release(&self.0, v), 616 + OrderingType::Relaxed => T::Repr::atomic_fetch_sub_relaxed(&self.0, v), 617 + } 618 + }; 619 + 620 + // SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. 621 + unsafe { from_repr(ret) } 622 + } 580 623 } 581 624 582 625 #[cfg(any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64))]
+5
rust/kernel/sync/atomic/internal.rs
··· 340 340 // SAFETY: `a.as_ptr()` is valid and properly aligned. 341 341 unsafe { bindings::#call(v, a.as_ptr().cast()) } 342 342 } 343 + 344 + fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { 345 + // SAFETY: `a.as_ptr()` guarantees the returned pointer is valid and properly aligned. 346 + unsafe { bindings::#call(v, a.as_ptr().cast()) } 347 + } 343 348 } 344 349 );