From 361edc94762dbf8f018b99c3972858bfe9d93ae0 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 27 May 2021 22:08:33 +0900 Subject: [PATCH] Remove uses of autocfg Detect platforms that do not support AtomicU64 by using the same way. AFAIK, this is more robust than the current way that uses autocfg. See also https://github.com/rust-lang/futures-rs/pull/2294. --- .github/workflows/ci.yml | 4 +- ci/no_atomic.sh | 25 ++++++++++++ ci/test.sh | 6 +-- crossbeam-utils/Cargo.toml | 3 -- crossbeam-utils/build.rs | 25 +++--------- crossbeam-utils/src/atomic/atomic_cell.rs | 44 ++++++++------------ crossbeam-utils/src/atomic/consume.rs | 10 +---- crossbeam-utils/src/lib.rs | 20 ++++----- crossbeam-utils/tests/atomic_cell.rs | 50 +++++++++++++++++------ no_atomic.rs | 41 +++++++++++++++++++ 10 files changed, 140 insertions(+), 88 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7c312d3d..d54f26b8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,9 @@ jobs: name: test env: RUST_VERSION: ${{ matrix.rust }} - TARGET: ${{ matrix.target }} + RUST_TARGET: ${{ matrix.target }} strategy: + fail-fast: false matrix: include: - rust: 1.36.0 @@ -63,6 +64,7 @@ jobs: env: RUST_VERSION: ${{ matrix.rust }} strategy: + fail-fast: false matrix: rust: - 1.36.0 diff --git a/ci/no_atomic.sh b/ci/no_atomic.sh index b589dbb17..c423ea3c4 100755 --- a/ci/no_atomic.sh +++ b/ci/no_atomic.sh @@ -26,6 +26,31 @@ for target in $(rustc --print target-list); do done echo "];" >>"$file" +{ + # Only crossbeam-utils actually uses this const. + echo "#[allow(dead_code)]" + echo "const NO_ATOMIC_64: &[&str] = &[" +} >>"$file" +for target in $(rustc --print target-list); do + res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \ + | jq -r "select(.\"max-atomic-width\" == 32)") + [[ -z "$res" ]] || echo " \"$target\"," >>"$file" +done +# It is not clear exactly what `"max-atomic-width" == null` means, but they +# actually seem to have the same max-atomic-width as the target-pointer-width. +# The targets currently included in this group are "mipsel-sony-psp", +# "thumbv4t-none-eabi", "thumbv6m-none-eabi", all of which are +# `"target-pointer-width" == "32"`, so assuming them `"max-atomic-width" == 32` +# for now. +for target in $(rustc --print target-list); do + res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \ + | jq -r "select(.\"max-atomic-width\" == null)") + [[ -z "$res" ]] || echo " \"$target\"," >>"$file" +done +echo "];" >>"$file" + +# There is no `"max-atomic-width" == 16` or `"max-atomic-width" == 8` targets. + # `"max-atomic-width" == 0` means that atomic is not supported at all. { # Only crossbeam-utils actually uses this const. diff --git a/ci/test.sh b/ci/test.sh index c0c633d30..5bda4ff05 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -5,10 +5,10 @@ set -ex export RUSTFLAGS="-D warnings" -if [[ -n "$TARGET" ]]; then - # If TARGET is specified, use cross for testing. +if [[ -n "$RUST_TARGET" ]]; then + # If RUST_TARGET is specified, use cross for testing. cargo install cross - cross test --all --target "$TARGET" --exclude benchmarks -- --test-threads=1 + cross test --all --target "$RUST_TARGET" --exclude benchmarks -- --test-threads=1 # For now, the non-host target only runs tests. exit 0 diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 212671e59..14526cadf 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -42,8 +42,5 @@ lazy_static = { version = "1.4.0", optional = true } [target.'cfg(crossbeam_loom)'.dependencies] loom = { version = "0.5", optional = true } -[build-dependencies] -autocfg = "1.0.0" - [dev-dependencies] rand = "0.8" diff --git a/crossbeam-utils/build.rs b/crossbeam-utils/build.rs index e7fabbd0c..9c924adeb 100644 --- a/crossbeam-utils/build.rs +++ b/crossbeam-utils/build.rs @@ -2,8 +2,6 @@ use std::env; -use autocfg::AutoCfg; - include!("no_atomic.rs"); // The rustc-cfg strings below are *not* public API. Please let us know by @@ -31,25 +29,12 @@ fn main() { } if NO_ATOMIC.contains(&&*target) { println!("cargo:rustc-cfg=crossbeam_no_atomic"); + println!("cargo:rustc-cfg=crossbeam_no_atomic_64"); + } else if NO_ATOMIC_64.contains(&&*target) { + println!("cargo:rustc-cfg=crossbeam_no_atomic_64"); + } else { + // Otherwise, assuming `"max-atomic-width" == 64`. } - let cfg = match AutoCfg::new() { - Ok(cfg) => cfg, - Err(e) => { - println!( - "cargo:warning={}: unable to determine rustc version: {}", - env!("CARGO_PKG_NAME"), - e - ); - return; - } - }; - - cfg.emit_type_cfg("core::sync::atomic::AtomicU8", "has_atomic_u8"); - cfg.emit_type_cfg("core::sync::atomic::AtomicU16", "has_atomic_u16"); - cfg.emit_type_cfg("core::sync::atomic::AtomicU32", "has_atomic_u32"); - cfg.emit_type_cfg("core::sync::atomic::AtomicU64", "has_atomic_u64"); - cfg.emit_type_cfg("core::sync::atomic::AtomicU128", "has_atomic_u128"); - println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index ad094b277..d911b9f4d 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -497,26 +497,19 @@ macro_rules! impl_arithmetic { }; } -#[cfg(has_atomic_u8)] impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);"); -#[cfg(all(has_atomic_u8, not(crossbeam_loom)))] impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);"); -#[cfg(has_atomic_u16)] impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);"); -#[cfg(all(has_atomic_u16, not(crossbeam_loom)))] impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);"); -#[cfg(has_atomic_u32)] impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);"); -#[cfg(all(has_atomic_u32, not(crossbeam_loom)))] impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);"); -#[cfg(has_atomic_u64)] +#[cfg(not(crossbeam_no_atomic_64))] impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);"); -#[cfg(all(has_atomic_u64, not(crossbeam_loom)))] +#[cfg(not(crossbeam_no_atomic_64))] impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);"); -#[cfg(all(has_atomic_u128, not(crossbeam_loom)))] -impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);"); -#[cfg(all(has_atomic_u128, not(crossbeam_loom)))] -impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);"); +// TODO: AtomicU128 is unstable +// impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);"); +// impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);"); impl_arithmetic!( usize, @@ -809,16 +802,13 @@ macro_rules! atomic { atomic!(@check, $t, AtomicUnit, $a, $atomic_op); atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op); - #[cfg(has_atomic_u8)] atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); - #[cfg(has_atomic_u16)] atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); - #[cfg(has_atomic_u32)] atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); - #[cfg(has_atomic_u64)] + #[cfg(not(crossbeam_no_atomic_64))] atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); - #[cfg(has_atomic_u128)] - atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); + // TODO: AtomicU128 is unstable + // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); #[cfg(crossbeam_loom)] unimplemented!("loom does not support non-atomic atomic ops"); @@ -831,17 +821,15 @@ macro_rules! atomic { /// Returns `true` if operations on `AtomicCell` are lock-free. const fn atomic_is_lock_free() -> bool { // HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in Rust 1.36. - let is_lock_free = can_transmute::() | can_transmute::(); - #[cfg(has_atomic_u8)] - let is_lock_free = is_lock_free | can_transmute::(); - #[cfg(has_atomic_u16)] - let is_lock_free = is_lock_free | can_transmute::(); - #[cfg(has_atomic_u32)] - let is_lock_free = is_lock_free | can_transmute::(); - #[cfg(has_atomic_u64)] + let is_lock_free = can_transmute::() + | can_transmute::() + | can_transmute::() + | can_transmute::() + | can_transmute::(); + #[cfg(not(crossbeam_no_atomic_64))] let is_lock_free = is_lock_free | can_transmute::(); - #[cfg(has_atomic_u128)] - let is_lock_free = is_lock_free | can_transmute::(); + // TODO: AtomicU128 is unstable + // let is_lock_free = is_lock_free | can_transmute::(); is_lock_free } diff --git a/crossbeam-utils/src/atomic/consume.rs b/crossbeam-utils/src/atomic/consume.rs index f28e32bbf..277b370a5 100644 --- a/crossbeam-utils/src/atomic/consume.rs +++ b/crossbeam-utils/src/atomic/consume.rs @@ -68,21 +68,15 @@ macro_rules! impl_atomic { impl_atomic!(AtomicBool, bool); impl_atomic!(AtomicUsize, usize); impl_atomic!(AtomicIsize, isize); -#[cfg(has_atomic_u8)] impl_atomic!(AtomicU8, u8); -#[cfg(has_atomic_u8)] impl_atomic!(AtomicI8, i8); -#[cfg(has_atomic_u16)] impl_atomic!(AtomicU16, u16); -#[cfg(has_atomic_u16)] impl_atomic!(AtomicI16, i16); -#[cfg(has_atomic_u32)] impl_atomic!(AtomicU32, u32); -#[cfg(has_atomic_u32)] impl_atomic!(AtomicI32, i32); -#[cfg(has_atomic_u64)] +#[cfg(not(crossbeam_no_atomic_64))] impl_atomic!(AtomicU64, u64); -#[cfg(has_atomic_u64)] +#[cfg(not(crossbeam_no_atomic_64))] impl_atomic!(AtomicI64, i64); #[cfg(not(crossbeam_no_atomic))] diff --git a/crossbeam-utils/src/lib.rs b/crossbeam-utils/src/lib.rs index 6f9df04ae..191c5a17d 100644 --- a/crossbeam-utils/src/lib.rs +++ b/crossbeam-utils/src/lib.rs @@ -46,7 +46,8 @@ mod primitive { pub(crate) mod atomic { pub(crate) use loom::sync::atomic::spin_loop_hint; pub(crate) use loom::sync::atomic::{ - AtomicBool, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, + AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, + AtomicU32, AtomicU64, AtomicU8, AtomicUsize, }; // FIXME: loom does not support compiler_fence at the moment. @@ -70,19 +71,12 @@ mod primitive { #[allow(deprecated)] pub(crate) use core::sync::atomic::spin_loop_hint; #[cfg(not(crossbeam_no_atomic))] - pub(crate) use core::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize}; - #[cfg(not(crossbeam_no_atomic))] - #[cfg(has_atomic_u16)] - pub(crate) use core::sync::atomic::{AtomicI16, AtomicU16}; - #[cfg(not(crossbeam_no_atomic))] - #[cfg(has_atomic_u32)] - pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32}; - #[cfg(not(crossbeam_no_atomic))] - #[cfg(has_atomic_u64)] + pub(crate) use core::sync::atomic::{ + AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, + AtomicU8, AtomicUsize, + }; + #[cfg(not(crossbeam_no_atomic_64))] pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64}; - #[cfg(not(crossbeam_no_atomic))] - #[cfg(has_atomic_u8)] - pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8}; } #[cfg(feature = "std")] diff --git a/crossbeam-utils/tests/atomic_cell.rs b/crossbeam-utils/tests/atomic_cell.rs index 3d91d81d6..c4c2c2c2f 100644 --- a/crossbeam-utils/tests/atomic_cell.rs +++ b/crossbeam-utils/tests/atomic_cell.rs @@ -1,3 +1,4 @@ +use std::mem; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; @@ -8,18 +9,43 @@ fn is_lock_free() { struct UsizeWrap(usize); struct U8Wrap(bool); struct I16Wrap(i16); - - assert_eq!(AtomicCell::::is_lock_free(), true); - assert_eq!(AtomicCell::::is_lock_free(), true); - assert_eq!(AtomicCell::::is_lock_free(), true); - - assert_eq!(AtomicCell::::is_lock_free(), cfg!(has_atomic_u8)); - assert_eq!(AtomicCell::::is_lock_free(), cfg!(has_atomic_u8)); - assert_eq!(AtomicCell::::is_lock_free(), cfg!(has_atomic_u8)); - - assert_eq!(AtomicCell::::is_lock_free(), cfg!(has_atomic_u16)); - - assert_eq!(AtomicCell::::is_lock_free(), cfg!(has_atomic_u128)); + #[repr(align(8))] + struct U64Align8(u64); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::<()>::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than + // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment + // of `AtomicU64` is `8`, so `AtomicCell` is not lock-free. + assert_eq!( + AtomicCell::::is_lock_free(), + cfg!(not(crossbeam_no_atomic_64)) && cfg!(target_pointer_width = "64") + ); + assert_eq!(mem::size_of::(), 8); + assert_eq!(mem::align_of::(), 8); + assert_eq!( + AtomicCell::::is_lock_free(), + cfg!(not(crossbeam_no_atomic_64)) + ); + + // AtomicU128 is unstable + assert!(!AtomicCell::::is_lock_free()); } #[test] diff --git a/no_atomic.rs b/no_atomic.rs index 015a115ed..522b3b8ac 100644 --- a/no_atomic.rs +++ b/no_atomic.rs @@ -10,6 +10,47 @@ const NO_ATOMIC_CAS: &[&str] = &[ "thumbv6m-none-eabi", ]; #[allow(dead_code)] +const NO_ATOMIC_64: &[&str] = &[ + "arm-linux-androideabi", + "armebv7r-none-eabi", + "armebv7r-none-eabihf", + "armv4t-unknown-linux-gnueabi", + "armv5te-unknown-linux-gnueabi", + "armv5te-unknown-linux-musleabi", + "armv5te-unknown-linux-uclibceabi", + "armv7r-none-eabi", + "armv7r-none-eabihf", + "hexagon-unknown-linux-musl", + "mips-unknown-linux-gnu", + "mips-unknown-linux-musl", + "mips-unknown-linux-uclibc", + "mipsel-unknown-linux-gnu", + "mipsel-unknown-linux-musl", + "mipsel-unknown-linux-uclibc", + "mipsel-unknown-none", + "mipsisa32r6-unknown-linux-gnu", + "mipsisa32r6el-unknown-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc-unknown-linux-gnuspe", + "powerpc-unknown-linux-musl", + "powerpc-unknown-netbsd", + "powerpc-unknown-openbsd", + "powerpc-wrs-vxworks", + "powerpc-wrs-vxworks-spe", + "riscv32gc-unknown-linux-gnu", + "riscv32gc-unknown-linux-musl", + "riscv32imac-unknown-none-elf", + "thumbv7em-none-eabi", + "thumbv7em-none-eabihf", + "thumbv7m-none-eabi", + "thumbv8m.base-none-eabi", + "thumbv8m.main-none-eabi", + "thumbv8m.main-none-eabihf", + "mipsel-sony-psp", + "thumbv4t-none-eabi", + "thumbv6m-none-eabi", +]; +#[allow(dead_code)] const NO_ATOMIC: &[&str] = &[ "avr-unknown-gnu-atmega328", "msp430-none-elf",