Struct Atomic

Source
pub struct Atomic<T: AtomicType>(/* private fields */);
Expand description

A memory location which can be safely modified from multiple execution contexts.

This has the same size, alignment and bit validity as the underlying type T. And it disables niche optimization for the same reason as UnsafeCell.

The atomic operations are implemented in a way that is fully compatible with the Linux Kernel Memory (Consistency) Model, hence they should be modeled as the corresponding LKMM atomic primitives. With the help of Atomic::from_ptr() and Atomic::as_ptr(), this provides a way to interact with C-side atomic operations (including those without the atomic prefix, e.g. READ_ONCE(), WRITE_ONCE(), smp_load_acquire() and smp_store_release()).

§Invariants

self.0 is a valid T.

Implementations§

Source§

impl<T: AtomicType> Atomic<T>

Source

pub const fn new(v: T) -> Self

Creates a new atomic T.

Source

pub unsafe fn from_ptr<'a>(ptr: *mut T) -> &'a Self
where T: Sync,

Creates a reference to an atomic T from a pointer of T.

This usually is used when communicating with C side or manipulating a C struct, see examples below.

§Safety
  • ptr is aligned to align_of::<T>().
  • ptr is valid for reads and writes for 'a.
  • For the duration of 'a, other accesses to *ptr must not cause data races (defined by LKMM) against atomic operations on the returned reference. Note that if all other accesses are atomic, then this safety requirement is trivially fulfilled.
§Examples

Using Atomic::from_ptr() combined with Atomic::load() or Atomic::store() can achieve the same functionality as READ_ONCE()/smp_load_acquire() or WRITE_ONCE()/smp_store_release() in C side:

use kernel::sync::atomic::{Atomic, Relaxed, Release};

// Assume there is a C struct `foo`.
mod cbindings {
    #[repr(C)]
    pub(crate) struct foo {
        pub(crate) a: i32,
        pub(crate) b: i32
    }
}

let tmp = Opaque::new(cbindings::foo { a: 1, b: 2 });

// struct foo *foo_ptr = ..;
let foo_ptr = tmp.get();

// SAFETY: `foo_ptr` is valid, and `.a` is in bounds.
let foo_a_ptr = unsafe { &raw mut (*foo_ptr).a };

// a = READ_ONCE(foo_ptr->a);
//
// SAFETY: `foo_a_ptr` is valid for read, and all other accesses on it is atomic, so no
// data race.
let a = unsafe { Atomic::from_ptr(foo_a_ptr) }.load(Relaxed);

// smp_store_release(&foo_ptr->a, 2);
//
// SAFETY: `foo_a_ptr` is valid for writes, and all other accesses on it is atomic, so
// no data race.
unsafe { Atomic::from_ptr(foo_a_ptr) }.store(2, Release);
Source

pub const fn as_ptr(&self) -> *mut T

Returns a pointer to the underlying atomic T.

Note that use of the return pointer must not cause data races defined by LKMM.

§Guarantees

The returned pointer is valid and properly aligned (i.e. aligned to align_of::<T>()).

Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to the underlying atomic T.

This is safe because the mutable reference of the atomic T guarantees exclusive access.

Source§

impl<T: AtomicType> Atomic<T>
where T::Repr: AtomicBasicOps,

Source

pub fn load<Ordering: AcquireOrRelaxed>(&self, _: Ordering) -> T

Loads the value from the atomic T.

§Examples
use kernel::sync::atomic::{Atomic, Relaxed};

let x = Atomic::new(42i32);

assert_eq!(42, x.load(Relaxed));

let x = Atomic::new(42i64);

assert_eq!(42, x.load(Relaxed));
Source

pub fn store<Ordering: ReleaseOrRelaxed>(&self, v: T, _: Ordering)

Stores a value to the atomic T.

§Examples
use kernel::sync::atomic::{Atomic, Relaxed};

let x = Atomic::new(42i32);

assert_eq!(42, x.load(Relaxed));

x.store(43, Relaxed);

assert_eq!(43, x.load(Relaxed));
Source§

impl<T: AtomicType> Atomic<T>
where T::Repr: AtomicExchangeOps,

Source

pub fn xchg<Ordering: Ordering>(&self, v: T, _: Ordering) -> T

Atomic exchange.

Atomically updates *self to v and returns the old value of *self.

§Examples
use kernel::sync::atomic::{Atomic, Acquire, Relaxed};

let x = Atomic::new(42);

assert_eq!(42, x.xchg(52, Acquire));
assert_eq!(52, x.load(Relaxed));
Source

pub fn cmpxchg<Ordering: Ordering>( &self, old: T, new: T, o: Ordering, ) -> Result<T, T>

Atomic compare and exchange.

If *self == old, atomically updates *self to new. Otherwise, *self is not modified.

Compare: The comparison is done via the byte level comparison between *self and old.

Ordering: When succeeds, provides the corresponding ordering as the Ordering type parameter indicates, and a failed one doesn’t provide any ordering, the load part of a failed cmpxchg is a Relaxed load.

Returns Ok(value) if cmpxchg succeeds, and value is guaranteed to be equal to old, otherwise returns Err(value), and value is the current value of *self.

§Examples
use kernel::sync::atomic::{Atomic, Full, Relaxed};

let x = Atomic::new(42);

// Checks whether cmpxchg succeeded.
let success = x.cmpxchg(52, 64, Relaxed).is_ok();

// Checks whether cmpxchg failed.
let failure = x.cmpxchg(52, 64, Relaxed).is_err();

// Uses the old value if failed, probably re-try cmpxchg.
match x.cmpxchg(52, 64, Relaxed) {
    Ok(_) => { },
    Err(old) => {
        // do something with `old`.
    }
}

// Uses the latest value regardlessly, same as atomic_cmpxchg() in C.
let latest = x.cmpxchg(42, 64, Full).unwrap_or_else(|old| old);
assert_eq!(64, x.load(Relaxed));
Source§

impl<T: AtomicType> Atomic<T>
where T::Repr: AtomicArithmeticOps,

Source

pub fn add<Rhs>(&self, v: Rhs, _: Relaxed)
where T: AtomicAdd<Rhs>,

Atomic add.

Atomically updates *self to (*self).wrapping_add(v).

§Examples
use kernel::sync::atomic::{Atomic, Relaxed};

let x = Atomic::new(42);

assert_eq!(42, x.load(Relaxed));

x.add(12, Relaxed);

assert_eq!(54, x.load(Relaxed));
Source

pub fn fetch_add<Rhs, Ordering: Ordering>(&self, v: Rhs, _: Ordering) -> T
where T: AtomicAdd<Rhs>,

Atomic fetch and add.

Atomically updates *self to (*self).wrapping_add(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!(54, { x.fetch_add(12, Acquire); x.load(Relaxed) });

let x = Atomic::new(42);

assert_eq!(42, x.load(Relaxed));

assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } );

Trait Implementations§

Auto Trait Implementations§

§

impl<T> !Freeze for Atomic<T>

§

impl<T> !RefUnwindSafe for Atomic<T>

§

impl<T> Send for Atomic<T>

§

impl<T> Unpin for Atomic<T>
where <T as AtomicType>::Repr: Unpin,

§

impl<T> UnwindSafe for Atomic<T>
where <T as AtomicType>::Repr: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Init<T> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PinInit<T> for T

Source§

unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.