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());