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 c385325
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 72 deletions.
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
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
6 changes: 1 addition & 5 deletions crossbeam-utils/src/lib.rs
Expand Up @@ -72,16 +72,12 @@ mod primitive {
#[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)]
#[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};
}

Expand Down
22 changes: 14 additions & 8 deletions crossbeam-utils/tests/atomic_cell.rs
Expand Up @@ -9,17 +9,23 @@ 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::<bool>::is_lock_free());
assert!(AtomicCell::<U8Wrap>::is_lock_free());

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

assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
assert_eq!(
AtomicCell::<u64>::is_lock_free(),
cfg!(not(crossbeam_no_atomic_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 c385325

Please sign in to comment.