Skip to content

Commit

Permalink
Remove uses of autocfg
Browse files Browse the repository at this point in the history
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 rust-lang/futures-rs#2294.
  • Loading branch information
taiki-e committed May 27, 2021
1 parent 7e6c097 commit debc101
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 84 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Expand Up @@ -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
Expand Down Expand Up @@ -63,6 +64,7 @@ jobs:
env:
RUST_VERSION: ${{ matrix.rust }}
strategy:
fail-fast: false
matrix:
rust:
- 1.36.0
Expand Down
25 changes: 25 additions & 0 deletions ci/no_atomic.sh
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions ci/test.sh
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions crossbeam-utils/Cargo.toml
Expand Up @@ -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"
25 changes: 5 additions & 20 deletions crossbeam-utils/build.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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");
}
44 changes: 16 additions & 28 deletions crossbeam-utils/src/atomic/atomic_cell.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand All @@ -831,17 +821,15 @@ macro_rules! atomic {
/// Returns `true` if operations on `AtomicCell<T>` are lock-free.
const fn atomic_is_lock_free<T>() -> 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::<T, AtomicUnit>() | can_transmute::<T, atomic::AtomicUsize>();
#[cfg(has_atomic_u8)]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU8>();
#[cfg(has_atomic_u16)]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU16>();
#[cfg(has_atomic_u32)]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU32>();
#[cfg(has_atomic_u64)]
let is_lock_free = can_transmute::<T, AtomicUnit>()
| can_transmute::<T, atomic::AtomicUsize>()
| can_transmute::<T, atomic::AtomicU8>()
| can_transmute::<T, atomic::AtomicU16>()
| can_transmute::<T, atomic::AtomicU32>();
#[cfg(not(crossbeam_no_atomic_64))]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
#[cfg(has_atomic_u128)]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
// TODO: AtomicU128 is unstable
// let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
is_lock_free
}

Expand Down
10 changes: 2 additions & 8 deletions crossbeam-utils/src/atomic/consume.rs
Expand Up @@ -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))]
Expand Down
20 changes: 7 additions & 13 deletions crossbeam-utils/src/lib.rs
Expand Up @@ -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.
Expand All @@ -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")]
Expand Down
28 changes: 20 additions & 8 deletions crossbeam-utils/tests/atomic_cell.rs
Expand Up @@ -9,17 +9,29 @@ fn is_lock_free() {
struct U8Wrap(bool);
struct I16Wrap(i16);

assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
assert_eq!(AtomicCell::<isize>::is_lock_free(), true);
assert_eq!(AtomicCell::<UsizeWrap>::is_lock_free(), true);
assert!(AtomicCell::<usize>::is_lock_free());
assert!(AtomicCell::<isize>::is_lock_free());
assert!(AtomicCell::<UsizeWrap>::is_lock_free());

assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(has_atomic_u8));
assert_eq!(AtomicCell::<bool>::is_lock_free(), cfg!(has_atomic_u8));
assert_eq!(AtomicCell::<U8Wrap>::is_lock_free(), cfg!(has_atomic_u8));
assert!(AtomicCell::<u8>::is_lock_free());
assert!(AtomicCell::<i8>::is_lock_free());
assert!(AtomicCell::<bool>::is_lock_free());
assert!(AtomicCell::<U8Wrap>::is_lock_free());

assert_eq!(AtomicCell::<I16Wrap>::is_lock_free(), cfg!(has_atomic_u16));
assert!(AtomicCell::<u16>::is_lock_free());
assert!(AtomicCell::<i16>::is_lock_free());
assert!(AtomicCell::<I16Wrap>::is_lock_free());

assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
assert!(AtomicCell::<u32>::is_lock_free());
assert!(AtomicCell::<i32>::is_lock_free());

assert_eq!(
AtomicCell::<u64>::is_lock_free(),
cfg!(not(crossbeam_no_atomic_64)) && cfg!(target_pointer_width = "64")
);

// AtomicU128 is unstable
assert!(!AtomicCell::<u128>::is_lock_free());
}

#[test]
Expand Down
41 changes: 41 additions & 0 deletions no_atomic.rs
Expand Up @@ -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",
Expand Down

0 comments on commit debc101

Please sign in to comment.