diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/portable-atomic/src/lib.rs | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/portable-atomic/src/lib.rs')
-rw-r--r-- | vendor/portable-atomic/src/lib.rs | 246 |
1 files changed, 194 insertions, 52 deletions
diff --git a/vendor/portable-atomic/src/lib.rs b/vendor/portable-atomic/src/lib.rs index 4be988e8b..21d743d71 100644 --- a/vendor/portable-atomic/src/lib.rs +++ b/vendor/portable-atomic/src/lib.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + /*! <!-- tidy:crate-doc:start --> Portable atomic types including support for 128-bit atomics, atomic float, etc. @@ -8,7 +10,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc. - Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR) - Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise) - Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485). -- Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. +- Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr) and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. - Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc. <!-- TODO: @@ -162,7 +164,7 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... If dynamic dispatching by run-time CPU feature detection is enabled, it allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE (aarch64). Note: - - Dynamic detection is currently only enabled in Rust 1.61+ for aarch64, in Rust 1.59+ (AVX) or 1.69+ (CMPXCHG16B) for x86_64, nightly only for powerpc64 (disabled by default), otherwise it works the same as when this cfg is set. + - Dynamic detection is currently only enabled in Rust 1.59+ for aarch64, in Rust 1.59+ (AVX) or 1.69+ (CMPXCHG16B) for x86_64, nightly only for powerpc64 (disabled by default), otherwise it works the same as when this cfg is set. - If the required target features are enabled at compile-time, the atomic operations are inlined. - This is compatible with no-std (as with all features except `std`). - On some targets, run-time detection is disabled by default mainly for compatibility with older versions of operating systems or incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) @@ -194,33 +196,33 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ) ))] #![warn( - improper_ctypes, - missing_debug_implementations, - missing_docs, rust_2018_idioms, single_use_lifetimes, - unreachable_pub -)] -#![cfg_attr(not(portable_atomic_no_unsafe_op_in_unsafe_fn), warn(unsafe_op_in_unsafe_fn))] // unsafe_op_in_unsafe_fn requires Rust 1.52 -#![cfg_attr(portable_atomic_no_unsafe_op_in_unsafe_fn, allow(unused_unsafe))] -#![warn( + unreachable_pub, clippy::pedantic, - // lints for public library + // Lints that may help when writing public library. + missing_debug_implementations, + missing_docs, clippy::alloc_instead_of_core, clippy::exhaustive_enums, clippy::exhaustive_structs, + clippy::impl_trait_in_params, + clippy::missing_inline_in_public_items, clippy::std_instead_of_alloc, clippy::std_instead_of_core, - // lints that help writing unsafe code + // Lints that may help when writing unsafe code. + improper_ctypes, + // improper_ctypes_definitions, // requires Rust 1.46 + // unsafe_op_in_unsafe_fn, // set conditionally since it requires Rust 1.52 clippy::as_ptr_cast_mut, clippy::default_union_representation, + clippy::inline_asm_x86_att_syntax, clippy::trailing_empty_array, clippy::transmute_undefined_repr, clippy::undocumented_unsafe_blocks, - // misc - clippy::inline_asm_x86_att_syntax, - clippy::missing_inline_in_public_items, )] +#![cfg_attr(not(portable_atomic_no_unsafe_op_in_unsafe_fn), warn(unsafe_op_in_unsafe_fn))] // unsafe_op_in_unsafe_fn requires Rust 1.52 +#![cfg_attr(portable_atomic_no_unsafe_op_in_unsafe_fn, allow(unused_unsafe))] #![allow( clippy::cast_lossless, clippy::doc_markdown, @@ -246,8 +248,8 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... target_arch = "avr", target_arch = "msp430", all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core), - all(portable_atomic_unstable_asm_experimental_arch, target_arch = "powerpc64"), - all(portable_atomic_unstable_asm_experimental_arch, target_arch = "s390x"), + all(target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch), + all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), ), ), feature(asm_experimental_arch) @@ -256,22 +258,13 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... // These features are already stabilized or have already been removed from compilers, // and can safely be enabled for old nightly as long as version detection works. // - cfg(target_has_atomic) -// - #[target_feature(enable = "lse")] on AArch64 // - #[target_feature(enable = "cmpxchg16b")] on x86_64 // - asm! on ARM, AArch64, RISC-V, x86_64 // - llvm_asm! on AVR (tier 3) and MSP430 (tier 3) -// - #[instruction_set] on non-Linux pre-v6 ARM (tier 3) +// - #[instruction_set] on non-Linux/Android pre-v6 ARM (tier 3) #![cfg_attr(portable_atomic_unstable_cfg_target_has_atomic, feature(cfg_target_has_atomic))] #![cfg_attr( all( - target_arch = "aarch64", - portable_atomic_unstable_aarch64_target_feature, - not(portable_atomic_no_outline_atomics), - ), - feature(aarch64_target_feature) -)] -#![cfg_attr( - all( target_arch = "x86_64", portable_atomic_unstable_cmpxchg16b_target_feature, not(portable_atomic_no_outline_atomics), @@ -284,13 +277,10 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... all( portable_atomic_unstable_asm, any( - all( - any(target_arch = "arm", target_arch = "riscv32", target_arch = "riscv64"), - not(target_has_atomic = "ptr"), - ), - all(target_arch = "arm", not(target_has_atomic = "64")), target_arch = "aarch64", - target_arch = "x86", + target_arch = "arm", + target_arch = "riscv32", + target_arch = "riscv64", target_arch = "x86_64", ), ), @@ -302,9 +292,9 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... )] #![cfg_attr( all( + target_arch = "arm", portable_atomic_unstable_isa_attribute, any(test, portable_atomic_unsafe_assume_single_core), - target_arch = "arm", not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(target_has_atomic = "ptr"), ), @@ -320,19 +310,28 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ), feature(core_intrinsics) )] -// This feature will be unnecessary once stdarch submodule in rust-lang/rust is -// updated to include https://github.com/rust-lang/stdarch/pull/1358. +// This feature is only enabled for old nightly because cmpxchg16b_intrinsic has been stabilized. #![cfg_attr( - all(target_arch = "x86_64", any(miri, portable_atomic_sanitize_thread)), + all( + target_arch = "x86_64", + portable_atomic_unstable_cmpxchg16b_intrinsic, + any(miri, portable_atomic_sanitize_thread), + ), feature(stdsimd) )] // docs.rs only #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr( all( - target_arch = "mips", portable_atomic_no_atomic_load_store, - not(feature = "critical-section"), + not(any( + target_arch = "avr", + target_arch = "bpf", + target_arch = "msp430", + target_arch = "riscv32", + target_arch = "riscv64", + feature = "critical-section", + )), ), allow(unused_imports, unused_macros) )] @@ -407,6 +406,9 @@ compile_error!("cfg(portable_atomic_disable_fiq) does not compatible with this t #[cfg(portable_atomic_s_mode)] #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] compile_error!("cfg(portable_atomic_s_mode) does not compatible with this target"); +#[cfg(portable_atomic_force_amo)] +#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] +compile_error!("cfg(portable_atomic_force_amo) does not compatible with this target"); #[cfg(portable_atomic_disable_fiq)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] @@ -418,6 +420,11 @@ compile_error!( compile_error!( "cfg(portable_atomic_s_mode) may only be used together with cfg(portable_atomic_unsafe_assume_single_core)" ); +#[cfg(portable_atomic_force_amo)] +#[cfg(not(portable_atomic_unsafe_assume_single_core))] +compile_error!( + "cfg(portable_atomic_force_amo) may only be used together with cfg(portable_atomic_unsafe_assume_single_core)" +); #[cfg(all(portable_atomic_unsafe_assume_single_core, feature = "critical-section"))] compile_error!( @@ -526,7 +533,7 @@ cfg_has_atomic_8! { cfg_has_atomic_cas! { // See https://github.com/rust-lang/rust/pull/114034 for details. // https://github.com/rust-lang/rust/blob/9339f446a5302cd5041d3f3b5e59761f36699167/library/core/src/sync/atomic.rs#L134 -// https://godbolt.org/z/EvPTfPh44 +// https://godbolt.org/z/5W85abT58 #[cfg(portable_atomic_no_cfg_target_has_atomic)] const EMULATE_ATOMIC_BOOL: bool = cfg!(all( not(portable_atomic_no_atomic_cas), @@ -600,6 +607,39 @@ impl AtomicBool { Self { v: core::cell::UnsafeCell::new(v as u8) } } + /// Creates a new `AtomicBool` from a pointer. + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can + /// be bigger than `align_of::<bool>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value + /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned + /// value (or vice-versa). + /// * In other words, time periods where the value is accessed atomically may not overlap + /// with periods where the value is accessed non-atomically. + /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the + /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. + /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done + /// from the same thread. + /// * If this atomic type is *not* lock-free: + /// * Any accesses to the value behind `ptr` must have a happens-before relationship + /// with accesses via the returned value (or vice-versa). + /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must + /// be compatible with operations performed by this atomic type. + /// * This method must not be used to create overlapping or mixed-size atomic accesses, as + /// these are not supported by the memory model. + /// + /// [valid]: core::ptr#safety + #[inline] + #[must_use] + pub unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self { + #[allow(clippy::cast_ptr_alignment)] + // SAFETY: guaranteed by the caller + unsafe { &*(ptr as *mut Self) } + } + /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary @@ -662,9 +702,8 @@ impl AtomicBool { unsafe { &mut *(self.v.get() as *mut bool) } } - // TODO: Add from_mut/get_mut_slice/from_mut_slice/from_ptr once it is stable on std atomic types. + // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 - // https://github.com/rust-lang/rust/issues/108652 /// Consumes the atomic and returns the contained value. /// @@ -1425,6 +1464,39 @@ impl<T> AtomicPtr<T> { Self { inner: imp::AtomicPtr::new(p) } } + /// Creates a new `AtomicPtr` from a pointer. + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this + /// can be bigger than `align_of::<*mut T>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value + /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned + /// value (or vice-versa). + /// * In other words, time periods where the value is accessed atomically may not overlap + /// with periods where the value is accessed non-atomically. + /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the + /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. + /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done + /// from the same thread. + /// * If this atomic type is *not* lock-free: + /// * Any accesses to the value behind `ptr` must have a happens-before relationship + /// with accesses via the returned value (or vice-versa). + /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must + /// be compatible with operations performed by this atomic type. + /// * This method must not be used to create overlapping or mixed-size atomic accesses, as + /// these are not supported by the memory model. + /// + /// [valid]: core::ptr#safety + #[inline] + #[must_use] + pub unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self { + #[allow(clippy::cast_ptr_alignment)] + // SAFETY: guaranteed by the caller + unsafe { &*(ptr as *mut Self) } + } + /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary @@ -1487,9 +1559,8 @@ impl<T> AtomicPtr<T> { self.inner.get_mut() } - // TODO: Add from_mut/get_mut_slice/from_mut_slice/from_ptr once it is stable on std atomic types. + // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 - // https://github.com/rust-lang/rust/issues/108652 /// Consumes the atomic and returns the contained value. /// @@ -2160,7 +2231,7 @@ impl<T> AtomicPtr<T> { #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); - strict::addr(self.fetch_or(mask, order)) & mask != 0 + self.fetch_or(mask, order) as usize & mask != 0 } #[cfg(not(miri))] { @@ -2205,7 +2276,7 @@ impl<T> AtomicPtr<T> { #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); - strict::addr(self.fetch_and(!mask, order)) & mask != 0 + self.fetch_and(!mask, order) as usize & mask != 0 } #[cfg(not(miri))] { @@ -2250,7 +2321,7 @@ impl<T> AtomicPtr<T> { #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); - strict::addr(self.fetch_xor(mask, order)) & mask != 0 + self.fetch_xor(mask, order) as usize & mask != 0 } #[cfg(not(miri))] { @@ -2380,6 +2451,42 @@ let atomic_forty_two = ", stringify!($atomic_type), "::new(42); } doc_comment! { + concat!("Creates a new reference to an atomic integer from a pointer. + +# Safety + +* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this + can be bigger than `align_of::<", stringify!($int_type), ">()`). +* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. +* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value + behind `ptr` must have a happens-before relationship with atomic accesses via + the returned value (or vice-versa). + * In other words, time periods where the value is accessed atomically may not + overlap with periods where the value is accessed non-atomically. + * This requirement is trivially satisfied if `ptr` is never used non-atomically + for the duration of lifetime `'a`. Most use cases should be able to follow + this guideline. + * This requirement is also trivially satisfied if all accesses (atomic or not) are + done from the same thread. +* If this atomic type is *not* lock-free: + * Any accesses to the value behind `ptr` must have a happens-before relationship + with accesses via the returned value (or vice-versa). + * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must + be compatible with operations performed by this atomic type. +* This method must not be used to create overlapping or mixed-size atomic + accesses, as these are not supported by the memory model. + +[valid]: core::ptr#safety"), + #[inline] + #[must_use] + pub unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self { + #[allow(clippy::cast_ptr_alignment)] + // SAFETY: guaranteed by the caller + unsafe { &*(ptr as *mut Self) } + } + } + + doc_comment! { concat!("Returns `true` if operations on values of this type are lock-free. If the compiler or the platform doesn't support the necessary @@ -2445,9 +2552,8 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5); } } - // TODO: Add from_mut/get_mut_slice/from_mut_slice/from_ptr once it is stable on std atomic types. + // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 - // https://github.com/rust-lang/rust/issues/108652 doc_comment! { concat!("Consumes the atomic and returns the contained value. @@ -3443,6 +3549,42 @@ This type has the same in-memory representation as the underlying floating point Self { inner: imp::float::$atomic_type::new(v) } } + doc_comment! { + concat!("Creates a new reference to an atomic float from a pointer. + +# Safety + +* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this + can be bigger than `align_of::<", stringify!($float_type), ">()`). +* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. +* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value + behind `ptr` must have a happens-before relationship with atomic accesses via + the returned value (or vice-versa). + * In other words, time periods where the value is accessed atomically may not + overlap with periods where the value is accessed non-atomically. + * This requirement is trivially satisfied if `ptr` is never used non-atomically + for the duration of lifetime `'a`. Most use cases should be able to follow + this guideline. + * This requirement is also trivially satisfied if all accesses (atomic or not) are + done from the same thread. +* If this atomic type is *not* lock-free: + * Any accesses to the value behind `ptr` must have a happens-before relationship + with accesses via the returned value (or vice-versa). + * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must + be compatible with operations performed by this atomic type. +* This method must not be used to create overlapping or mixed-size atomic + accesses, as these are not supported by the memory model. + +[valid]: core::ptr#safety"), + #[inline] + #[must_use] + pub unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self { + #[allow(clippy::cast_ptr_alignment)] + // SAFETY: guaranteed by the caller + unsafe { &*(ptr as *mut Self) } + } + } + /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary @@ -3477,7 +3619,7 @@ This type has the same in-memory representation as the underlying floating point self.inner.get_mut() } - // TODO: Add from_mut once it is stable on std atomic types. + // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 /// Consumes the atomic and returns the contained value. @@ -3752,7 +3894,7 @@ This type has the same in-memory representation as the underlying floating point #[cfg(not(portable_atomic_no_const_raw_ptr_deref))] doc_comment! { - concat!("Raw transmutation to `", stringify!($atomic_int_type), "`. + concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). @@ -3765,7 +3907,7 @@ This is `const fn` on Rust 1.58+."), } #[cfg(portable_atomic_no_const_raw_ptr_deref)] doc_comment! { - concat!("Raw transmutation to `", stringify!($atomic_int_type), "`. + concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). |