blob: cea71eb3f49001b468330a3fcb2051a41e14cc94 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR MIT
// -----------------------------------------------------------------------------
// Lock-free implementations
#[cfg(not(any(
all(
portable_atomic_no_atomic_load_store,
not(all(target_arch = "bpf", not(feature = "critical-section"))),
),
portable_atomic_unsafe_assume_single_core,
target_arch = "avr",
target_arch = "msp430",
)))]
#[cfg_attr(
portable_atomic_no_cfg_target_has_atomic,
cfg(not(all(
any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"),
portable_atomic_no_atomic_cas,
)))
)]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(not(all(
any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"),
not(target_has_atomic = "ptr"),
)))
)]
mod core_atomic;
// aarch64 128-bit atomics
#[cfg(all(
target_arch = "aarch64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(
all(any(miri, portable_atomic_sanitize_thread), portable_atomic_new_atomic_intrinsics),
path = "atomic128/intrinsics.rs"
)]
#[cfg_attr(
not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_new_atomic_intrinsics)),
path = "atomic128/aarch64.rs"
)]
mod aarch64;
// x86_64 128-bit atomics
#[cfg(all(
target_arch = "x86_64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
any(
target_feature = "cmpxchg16b",
portable_atomic_target_feature = "cmpxchg16b",
all(
feature = "fallback",
not(portable_atomic_no_cmpxchg16b_target_feature),
not(portable_atomic_no_outline_atomics),
not(any(target_env = "sgx", miri)),
),
),
))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "atomic128/intrinsics.rs")]
#[cfg_attr(not(any(miri, portable_atomic_sanitize_thread)), path = "atomic128/x86_64.rs")]
mod x86_64;
// powerpc64 128-bit atomics
#[cfg(all(
target_arch = "powerpc64",
portable_atomic_unstable_asm_experimental_arch,
any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
all(
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(powerpc64): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
target_os = "freebsd",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(
all(any(miri, portable_atomic_sanitize_thread), portable_atomic_llvm_15),
path = "atomic128/intrinsics.rs"
)]
#[cfg_attr(
not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_llvm_15)),
path = "atomic128/powerpc64.rs"
)]
mod powerpc64;
// s390x 128-bit atomics
#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "atomic128/intrinsics.rs")]
#[cfg_attr(not(any(miri, portable_atomic_sanitize_thread)), path = "atomic128/s390x.rs")]
mod s390x;
// pre-v6 ARM Linux 64-bit atomics
#[cfg(feature = "fallback")]
// Miri and Sanitizer do not support inline assembly.
#[cfg(all(
target_arch = "arm",
not(any(miri, portable_atomic_sanitize_thread)),
not(portable_atomic_no_asm),
any(target_os = "linux", target_os = "android"),
not(any(target_feature = "v6", portable_atomic_target_feature = "v6")),
not(portable_atomic_no_outline_atomics),
))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))]
mod arm_linux;
// MSP430 atomics
#[cfg(target_arch = "msp430")]
pub(crate) mod msp430;
// atomic load/store for RISC-V without A-extension
#[cfg(any(test, not(feature = "critical-section")))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(any(test, not(target_has_atomic = "ptr")))
)]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
mod riscv;
// x86-specific optimizations
// Miri and Sanitizer do not support inline assembly.
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(any(miri, portable_atomic_sanitize_thread)),
not(portable_atomic_no_asm),
))]
mod x86;
// -----------------------------------------------------------------------------
// Lock-based fallback implementations
#[cfg(feature = "fallback")]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))]
#[cfg(any(
test,
not(any(
all(
target_arch = "aarch64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
),
all(
target_arch = "x86_64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"),
),
all(
target_arch = "powerpc64",
portable_atomic_unstable_asm_experimental_arch,
any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
))
))]
mod fallback;
// -----------------------------------------------------------------------------
// Critical section based fallback implementations
// On AVR, we always use critical section based fallback implementation.
// AVR can be safely assumed to be single-core, so this is sound.
// https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1074
// MSP430 as well.
#[cfg(any(
all(test, target_os = "none"),
portable_atomic_unsafe_assume_single_core,
feature = "critical-section",
target_arch = "avr",
target_arch = "msp430",
))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(any(test, not(target_has_atomic = "ptr")))
)]
#[cfg(any(
target_arch = "arm",
target_arch = "avr",
target_arch = "msp430",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "xtensa",
feature = "critical-section",
))]
mod interrupt;
// -----------------------------------------------------------------------------
// Atomic float implementations
#[cfg(feature = "float")]
pub(crate) mod float;
// -----------------------------------------------------------------------------
#[cfg(not(any(
portable_atomic_no_atomic_load_store,
portable_atomic_unsafe_assume_single_core,
target_arch = "avr",
target_arch = "msp430",
)))]
#[cfg_attr(
portable_atomic_no_cfg_target_has_atomic,
cfg(not(all(
any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"),
portable_atomic_no_atomic_cas,
)))
)]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(not(all(
any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"),
not(target_has_atomic = "ptr"),
)))
)]
items! {
pub(crate) use self::core_atomic::{
AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize,
};
#[cfg_attr(
portable_atomic_no_cfg_target_has_atomic,
cfg(any(
not(portable_atomic_no_atomic_64),
not(any(target_pointer_width = "16", target_pointer_width = "32")),
))
)]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(any(
target_has_atomic = "64",
not(any(target_pointer_width = "16", target_pointer_width = "32")),
))
)]
pub(crate) use self::core_atomic::{AtomicI64, AtomicU64};
}
// bpf
#[cfg(all(
target_arch = "bpf",
portable_atomic_no_atomic_load_store,
not(feature = "critical-section"),
))]
pub(crate) use self::core_atomic::{AtomicI64, AtomicIsize, AtomicPtr, AtomicU64, AtomicUsize};
// RISC-V without A-extension & !(assume single core | critical section)
#[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
items! {
pub(crate) use self::riscv::{
AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize,
};
#[cfg(target_arch = "riscv64")]
pub(crate) use self::riscv::{AtomicI64, AtomicU64};
}
// no core atomic CAS & (assume single core | critical section) => critical section based fallback
#[cfg(any(
portable_atomic_unsafe_assume_single_core,
feature = "critical-section",
target_arch = "avr",
target_arch = "msp430",
))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
items! {
pub(crate) use self::interrupt::{
AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize,
};
#[cfg(any(not(target_pointer_width = "16"), feature = "fallback"))]
pub(crate) use self::interrupt::{AtomicI32, AtomicU32};
#[cfg(any(
not(any(target_pointer_width = "16", target_pointer_width = "32")),
feature = "fallback",
))]
pub(crate) use self::interrupt::{AtomicI64, AtomicU64};
#[cfg(feature = "fallback")]
pub(crate) use self::interrupt::{AtomicI128, AtomicU128};
}
// no core (64-bit | 128-bit) atomic & has CAS => use lock-base fallback
#[cfg(feature = "fallback")]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))]
items! {
#[cfg(not(all(
target_arch = "arm",
not(any(miri, portable_atomic_sanitize_thread)),
not(portable_atomic_no_asm),
any(target_os = "linux", target_os = "android"),
not(any(target_feature = "v6", portable_atomic_target_feature = "v6")),
not(portable_atomic_no_outline_atomics),
)))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))]
pub(crate) use self::fallback::{AtomicI64, AtomicU64};
#[cfg(not(any(
all(
target_arch = "aarch64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
),
all(
target_arch = "x86_64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
any(
target_feature = "cmpxchg16b",
portable_atomic_target_feature = "cmpxchg16b",
all(
feature = "fallback",
not(portable_atomic_no_cmpxchg16b_target_feature),
not(portable_atomic_no_outline_atomics),
not(any(target_env = "sgx", miri)),
),
),
),
all(
target_arch = "powerpc64",
portable_atomic_unstable_asm_experimental_arch,
any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
all(
feature = "fallback",
not(portable_atomic_no_outline_atomics),
portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
target_os = "freebsd",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
)))]
pub(crate) use self::fallback::{AtomicI128, AtomicU128};
}
// 64-bit atomics (platform-specific)
// pre-v6 ARM Linux
#[cfg(feature = "fallback")]
#[cfg(all(
target_arch = "arm",
not(any(miri, portable_atomic_sanitize_thread)),
not(portable_atomic_no_asm),
any(target_os = "linux", target_os = "android"),
not(any(target_feature = "v6", portable_atomic_target_feature = "v6")),
not(portable_atomic_no_outline_atomics),
))]
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))]
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))]
pub(crate) use self::arm_linux::{AtomicI64, AtomicU64};
// 128-bit atomics (platform-specific)
// aarch64
#[cfg(all(
target_arch = "aarch64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
))]
pub(crate) use self::aarch64::{AtomicI128, AtomicU128};
// x86_64 & (cmpxchg16b | outline-atomics)
#[cfg(all(
target_arch = "x86_64",
any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
any(
target_feature = "cmpxchg16b",
portable_atomic_target_feature = "cmpxchg16b",
all(
feature = "fallback",
not(portable_atomic_no_cmpxchg16b_target_feature),
not(portable_atomic_no_outline_atomics),
not(any(target_env = "sgx", miri)),
),
),
))]
pub(crate) use self::x86_64::{AtomicI128, AtomicU128};
// powerpc64 & (pwr8 | outline-atomics)
#[cfg(all(
target_arch = "powerpc64",
portable_atomic_unstable_asm_experimental_arch,
any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
all(
feature = "fallback",
not(portable_atomic_no_outline_atomics),
portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
target_os = "freebsd",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
))]
pub(crate) use self::powerpc64::{AtomicI128, AtomicU128};
// s390x
#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
pub(crate) use self::s390x::{AtomicI128, AtomicU128};