diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ca090d8a..c94b447b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -291,6 +291,8 @@ jobs:
- rust: nightly
target: riscv64gc-unknown-linux-gnu
flags: -Z codegen-backend=cranelift
+ # - rust: '1.84' # LLVM 19 (oldest stable version we can use asm on this target)
+ # target: s390x-unknown-linux-gnu
- rust: nightly-2023-05-09 # Rust 1.71, LLVM 16 (oldest version we can use asm_experimental_arch on this target)
target: s390x-unknown-linux-gnu
# - rust: nightly-2024-02-13 # Rust 1.78, LLVM 17
diff --git a/README.md b/README.md
index dfdcd6a1..29dd3d3d 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ portable-atomic = { version = "1.3", default-features = false, features = ["requ
## 128-bit atomics support
-Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), powerpc64 (nightly only), s390x (nightly only), and Arm64EC (nightly only), otherwise the fallback implementation is used.
+Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), s390x (Rust 1.84+), Arm64EC (nightly only), and powerpc64 (nightly only), otherwise the fallback implementation is used.
On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg.
diff --git a/build.rs b/build.rs
index 360cd8b0..31386d79 100644
--- a/build.rs
+++ b/build.rs
@@ -53,7 +53,7 @@ fn main() {
// Custom cfgs set by build script. Not public API.
// grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
println!(
- "cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_offset_of,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
+ "cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_offset_of,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
);
// TODO: handle multi-line target_feature_fallback
// grep -F 'target_feature_fallback("' build.rs | grep -Ev '^ *//' | sed -E 's/^.*target_feature_fallback\(//; s/",.*$/"/' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
@@ -127,7 +127,7 @@ fn main() {
println!("cargo:rustc-cfg=portable_atomic_no_const_mut_refs");
}
- // asm stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
+ // asm! on AArch64, Arm, RISC-V, x86, and x86_64 stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
let no_asm = !version.probe(59, 2021, 12, 15);
if no_asm {
if version.nightly
@@ -145,6 +145,27 @@ fn main() {
println!("cargo:rustc-cfg=portable_atomic_unstable_asm");
}
println!("cargo:rustc-cfg=portable_atomic_no_asm");
+ } else {
+ match target_arch {
+ "s390x" => {
+ // asm! on s390x stabilized in Rust 1.84 (nightly-2024-11-11): https://github.com/rust-lang/rust/pull/131258
+ if !version.probe(84, 2024, 11, 10) {
+ if version.nightly
+ && version.probe(71, 2023, 5, 8)
+ && is_allowed_feature("asm_experimental_arch")
+ {
+ // https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09).
+ // The part of this feature we use has not been changed since nightly-2023-05-09
+ // until it was stabilized in nightly-2024-11-11, so it can be safely enabled in
+ // nightly, which is older than nightly-2024-11-11.
+ println!("cargo:rustc-cfg=portable_atomic_unstable_asm_experimental_arch");
+ } else {
+ println!("cargo:rustc-cfg=portable_atomic_no_asm");
+ }
+ }
+ }
+ _ => {}
+ }
}
// feature(cfg_target_has_atomic) stabilized in Rust 1.60 (nightly-2022-02-11): https://github.com/rust-lang/rust/pull/93824
@@ -197,10 +218,8 @@ fn main() {
}
// https://github.com/rust-lang/rust/pull/93868 merged in Rust 1.60 (nightly-2022-02-13).
- // https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09).
if !no_asm
&& (target_arch == "powerpc64" && version.probe(60, 2022, 2, 12)
- || target_arch == "s390x" && version.probe(71, 2023, 5, 8)
|| target_arch == "arm64ec")
&& is_allowed_feature("asm_experimental_arch")
{
diff --git a/src/cfgs.rs b/src/cfgs.rs
index 6c08ffbe..5fbfc444 100644
--- a/src/cfgs.rs
+++ b/src/cfgs.rs
@@ -319,7 +319,7 @@ mod atomic_64_macros {
),
),
),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
+ all(target_arch = "s390x", not(portable_atomic_no_asm)),
))
)]
#[cfg_attr(
@@ -427,7 +427,7 @@ mod atomic_128_macros {
),
),
),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
+ all(target_arch = "s390x", not(portable_atomic_no_asm)),
)))
)]
#[cfg_attr(
diff --git a/src/imp/atomic128/README.md b/src/imp/atomic128/README.md
index 4e82c869..ba257f95 100644
--- a/src/imp/atomic128/README.md
+++ b/src/imp/atomic128/README.md
@@ -12,7 +12,7 @@ Here is the table of targets that support 128-bit atomics and the instructions u
| aarch64/arm64ec | ldxp/stxp or casp or ldp/ldiapp | ldxp/stxp or casp or stp/stilp/swpp | ldxp/stxp or casp | ldxp/stxp or casp/swpp/ldclrp/ldsetp | casp requires lse target feature, ldp/stp requires lse2 target feature, ldiapp/stilp requires lse2 and rcpc3 target features, swpp/ldclrp/ldsetp requires lse128 target feature.
Both compile-time and run-time detection are supported.
Requires rustc 1.59+ (aarch64) / nightly (arm64ec) |
| riscv64 | amocas.q | amocas.q | amocas.q | amocas.q | Experimental because LLVM marking the corresponding target feature as experimental. Requires experimental-zacas target feature. Both compile-time and run-time detection are supported (run-time detection is currently disabled by default).
Requires rustc 1.59+ |
| powerpc64 | lq | stq | lqarx/stqcx. | lqarx/stqcx. | Requires target-cpu pwr8+ (powerpc64le is pwr8 by default). Both compile-time and run-time detection are supported.
Requires nightly |
-| s390x | lpq | stpq | cdsg | cdsg | Requires nightly |
+| s390x | lpq | stpq | cdsg | cdsg | Requires rustc 1.84+ |
On compiler versions or platforms where these are not supported, the fallback implementation is used.
diff --git a/src/imp/atomic128/mod.rs b/src/imp/atomic128/mod.rs
index ce819c25..f2a1a134 100644
--- a/src/imp/atomic128/mod.rs
+++ b/src/imp/atomic128/mod.rs
@@ -79,7 +79,7 @@ pub(super) mod powerpc64;
pub(super) mod riscv64;
// s390x
-#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
+#[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "intrinsics.rs")]
pub(super) mod s390x;
diff --git a/src/imp/mod.rs b/src/imp/mod.rs
index 0bcc877d..5ec6de28 100644
--- a/src/imp/mod.rs
+++ b/src/imp/mod.rs
@@ -119,7 +119,7 @@ mod atomic128;
portable_atomic_target_feature = "quadword-atomics",
),
),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
+ all(target_arch = "s390x", not(portable_atomic_no_asm)),
))
))]
mod fallback;
@@ -363,7 +363,7 @@ items! {
),
),
),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
+ all(target_arch = "s390x", not(portable_atomic_no_asm)),
)))]
pub(crate) use self::fallback::{AtomicI128, AtomicU128};
}
@@ -475,5 +475,5 @@ pub(crate) use self::atomic128::riscv64::{AtomicI128, AtomicU128};
))]
pub(crate) use self::atomic128::powerpc64::{AtomicI128, AtomicU128};
// s390x
-#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
+#[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))]
pub(crate) use self::atomic128::s390x::{AtomicI128, AtomicU128};
diff --git a/src/lib.rs b/src/lib.rs
index 71b6fd56..9b3cc84e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,7 +46,7 @@ portable-atomic = { version = "1.3", default-features = false, features = ["requ
## 128-bit atomics support
-Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), powerpc64 (nightly only), s390x (nightly only), and Arm64EC (nightly only), otherwise the fallback implementation is used.
+Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), s390x (Rust 1.84+), Arm64EC (nightly only), and powerpc64 (nightly only), otherwise the fallback implementation is used.
On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg.
@@ -215,7 +215,7 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
#![allow(clippy::inline_always, clippy::used_underscore_items)]
// asm_experimental_arch
// AVR, MSP430, and Xtensa are tier 3 platforms and require nightly anyway.
-// On tier 2 platforms (arm64ec, powerpc64, and s390x), we use cfg set by build script to
+// On tier 2 platforms (arm64ec and powerpc64), we use cfg set by build script to
// determine whether this feature is available or not.
#![cfg_attr(
all(
@@ -226,7 +226,6 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core),
all(target_arch = "arm64ec", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
),
),
feature(asm_experimental_arch)
@@ -235,7 +234,7 @@ 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)
-// - asm! on Arm, AArch64, RISC-V, x86, x86_64
+// - asm! on AArch64, Arm, RISC-V, x86, x86_64, s390x
// - llvm_asm! on AVR (tier 3) and MSP430 (tier 3)
// - #[instruction_set] on non-Linux/Android pre-v6 Arm (tier 3)
// This also helps us test that our assembly code works with the minimum external
@@ -255,6 +254,10 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
),
feature(asm)
)]
+#![cfg_attr(
+ all(portable_atomic_unstable_asm_experimental_arch, target_arch = "s390x"),
+ feature(asm_experimental_arch)
+)]
#![cfg_attr(
all(any(target_arch = "avr", target_arch = "msp430"), portable_atomic_no_asm),
feature(llvm_asm)
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
index 0b63862a..a321f414 100644
--- a/src/tests/mod.rs
+++ b/src/tests/mod.rs
@@ -153,7 +153,7 @@ fn test_is_lock_free() {
portable_atomic_target_feature = "quadword-atomics",
),
),
- all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
+ all(target_arch = "s390x", not(portable_atomic_no_asm)),
)) {
assert!(AtomicI128::is_always_lock_free());
assert!(AtomicI128::is_lock_free());