rust-lang / rust

Empowering everyone to build reliable and efficient software.

Home Page:https://www.rust-lang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tracking Issue for arithmetic and certain bitwise ops on `AtomicPtr`

WaffleLapkin opened this issue · comments

Feature gate: #![feature(strict_provenance_atomic_ptr)]

This is a tracking issue for arithmetic and certain bitwise operations on AtomicPtr.
As part of the strict provenance experiment #95228.

This feature adds arithmetic (add, sub) and bitwise (or, end, xor) atomic operations for AtomicPtr in order to replace uses of AtomicUsize-but-actually-a-pointer to preserve provenance information for the compiler and remove usize->ptr casts from existing code.

Arithmetic ops behave as the their non-atomic wrapping versions. Bitwise ops behave as .map_addr(|x| x op val).

Public API

// core::sync::atomic

impl<T> AtomicPtr<T> {
    pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T;
    pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T;

    pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T;
    pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T;

    pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T;
    pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T;
    pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T;
}

Steps / History

  • Implementation: #96935
  • Final comment period (FCP)1
  • Stabilization PR

Unresolved Questions

  • Naming

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

In terms of implementation details, I think we should also improve the types at which we call the atomic_add and other core atomic intrinsics. Right now we pass them two pointers and then the backend has to know that the left one is actually a pointer and we care about its provenance, and the right one isn't. Ideally we'd give a pointer as first argument and an integer as second argument.

"The problem" with making rhs usize is that all atomic intrinsics are currently defined as *mut T -> T -> T, for example:

pub fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T;

Making the second argument of a different type will probably require compiler changes.

Indeed, and I think those compiler changes should be made. :)

I think ptr in method names (fetch_ptr_add and fetch_ptr_sub) is confusing, we are not adding/subtracting a pointer but instead just add/sub in units of T. IMO it's too similar to sub_ptr.

I think the only open question about this API is whether there is a better name for fetch_byte_{add,sub}/fetch_ptr_{add,sub} (rust-lang/libs-team#126 (comment))? Can we move forward towards stabilization? If those methods are still up for debate, fetch_{or,and,xor} are pretty straightforward additions (and probably the more common operations) so can probably be stabilized.

Why not just fetch_wrapping_{add, sub} rather than fetch_ptr_sub? ptr in the name seems redundant, and I would expect fetch_add to be the equivalent of <*const T>::add (not <*const T>::wrapping_add)

@tgross35 note that all atomic operations are wrapping, so wrapping is probably even more redundant than ptr 😅

I don't really like _ptr_ either, but it does disambiguate that it's in units of T, as opposed to fetch_byte_add.