From 138c956a054c26ea816574bb0e70c63ad55fa512 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 23 May 2021 13:55:53 +0900 Subject: [PATCH] Allow AtomicConsume to be used on targets that do not support atomic --- .github/workflows/ci.yml | 4 +-- build.rs | 32 --------------------- ci/check-features.sh | 15 ++++++---- ci/no_atomic.sh | 40 +++++++++++++++++++++++++++ ci/no_atomic_cas.sh | 27 ------------------ crossbeam-epoch/build.rs | 4 +-- crossbeam-epoch/no_atomic.rs | 1 + crossbeam-epoch/no_atomic_cas.rs | 1 - crossbeam-epoch/src/lib.rs | 6 ++-- crossbeam-queue/build.rs | 4 +-- crossbeam-queue/no_atomic.rs | 1 + crossbeam-queue/no_atomic_cas.rs | 1 - crossbeam-skiplist/build.rs | 4 +-- crossbeam-skiplist/no_atomic.rs | 1 + crossbeam-skiplist/no_atomic_cas.rs | 1 - crossbeam-utils/build.rs | 7 ++++- crossbeam-utils/no_atomic.rs | 1 + crossbeam-utils/no_atomic_cas.rs | 1 - crossbeam-utils/src/atomic/consume.rs | 14 ++++++---- crossbeam-utils/src/atomic/mod.rs | 8 +++--- crossbeam-utils/src/lib.rs | 14 ++++------ no_atomic_cas.rs => no_atomic.rs | 9 +++++- src/lib.rs | 1 - 23 files changed, 97 insertions(+), 100 deletions(-) delete mode 100644 build.rs create mode 100755 ci/no_atomic.sh delete mode 100755 ci/no_atomic_cas.sh create mode 120000 crossbeam-epoch/no_atomic.rs delete mode 120000 crossbeam-epoch/no_atomic_cas.rs create mode 120000 crossbeam-queue/no_atomic.rs delete mode 120000 crossbeam-queue/no_atomic_cas.rs create mode 120000 crossbeam-skiplist/no_atomic.rs delete mode 120000 crossbeam-skiplist/no_atomic_cas.rs create mode 120000 crossbeam-utils/no_atomic.rs delete mode 120000 crossbeam-utils/no_atomic_cas.rs rename no_atomic_cas.rs => no_atomic.rs (53%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0051f5f5e..0a1c1960c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,7 +86,7 @@ jobs: - name: dependency tree check run: ./ci/dependencies.sh - # When this job failed, run ci/no_atomic_cas.sh and commit result changes. + # When this job failed, run ci/no_atomic.sh and commit result changes. # TODO(taiki-e): Ideally, this should be automated using a bot that creates # PR when failed, but there is no bandwidth to implement it # right now... @@ -96,7 +96,7 @@ jobs: - uses: actions/checkout@v2 - name: Install Rust run: rustup update nightly && rustup default nightly - - run: ci/no_atomic_cas.sh + - run: ci/no_atomic.sh - run: git diff --exit-code # Check formatting. diff --git a/build.rs b/build.rs deleted file mode 100644 index ac41a83da..000000000 --- a/build.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![warn(rust_2018_idioms)] - -use std::env; - -include!("no_atomic_cas.rs"); - -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. -fn main() { - let target = match env::var("TARGET") { - Ok(target) => target, - Err(e) => { - println!( - "cargo:warning={}: unable to get TARGET environment variable: {}", - env!("CARGO_PKG_NAME"), - e - ); - return; - } - }; - - // Note that this is `no_*`, not `has_*`. This allows treating - // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't - // run. This is needed for compatibility with non-cargo build systems that - // don't run the build script. - if NO_ATOMIC_CAS.contains(&&*target) { - println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); - } - - println!("cargo:rerun-if-changed=no_atomic_cas.rs"); -} diff --git a/ci/check-features.sh b/ci/check-features.sh index c6901d0b7..17fc1a8c1 100755 --- a/ci/check-features.sh +++ b/ci/check-features.sh @@ -13,14 +13,19 @@ if [[ "$RUST_VERSION" != "nightly"* ]]; then # * `--no-dev-deps` - build without dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866 # * `--exclude benchmarks` - benchmarks doesn't published. # * `--skip nightly` - skip `nightly` feature as requires nightly compilers. - cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --skip nightly + cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --skip nightly else # On nightly, all feature combinations should work. - cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks + cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks - # Check for no_std environment. + # Build for no_std environment. + # thumbv7m-none-eabi supports atomic CAS. + # thumbv6m-none-eabi supports atomic, but not atomic CAS. + # riscv32i-unknown-none-elf does not support atomic at all. rustup target add thumbv7m-none-eabi rustup target add thumbv6m-none-eabi - cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv7m-none-eabi --skip std,default - cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default + rustup target add riscv32i-unknown-none-elf + cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv7m-none-eabi --skip std,default + cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default + cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target riscv32i-unknown-none-elf --skip std,default fi diff --git a/ci/no_atomic.sh b/ci/no_atomic.sh new file mode 100755 index 000000000..b589dbb17 --- /dev/null +++ b/ci/no_atomic.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Update the list of targets that do not support atomic/CAS operations. +# +# Usage: +# ./ci/no_atomic.sh + +set -euo pipefail +IFS=$'\n\t' + +cd "$(cd "$(dirname "$0")" && pwd)"/.. + +file="no_atomic.rs" + +{ + echo "// This file is @generated by $(basename "$0")." + echo "// It is not intended for manual editing." + echo "" +} >"$file" + +echo "const NO_ATOMIC_CAS: &[&str] = &[" >>"$file" +for target in $(rustc --print target-list); do + res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \ + | jq -r "select(.\"atomic-cas\" == false)") + [[ -z "$res" ]] || echo " \"$target\"," >>"$file" +done +echo "];" >>"$file" + +# `"max-atomic-width" == 0` means that atomic is not supported at all. +{ + # Only crossbeam-utils actually uses this const. + echo "#[allow(dead_code)]" + echo "const NO_ATOMIC: &[&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\" == 0)") + [[ -z "$res" ]] || echo " \"$target\"," >>"$file" +done +echo "];" >>"$file" diff --git a/ci/no_atomic_cas.sh b/ci/no_atomic_cas.sh deleted file mode 100755 index bc2e3500f..000000000 --- a/ci/no_atomic_cas.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Update the list of targets that do not support atomic CAS operations. -# -# Usage: -# ./ci/no_atomic_cas.sh - -set -euo pipefail -IFS=$'\n\t' - -cd "$(cd "$(dirname "$0")" && pwd)"/.. - -file="no_atomic_cas.rs" - -{ - echo "// This file is @generated by $(basename "$0")." - echo "// It is not intended for manual editing." - echo "" -} >"$file" - -echo "const NO_ATOMIC_CAS: &[&str] = &[" >>"$file" -for target in $(rustc --print target-list); do - res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \ - | jq -r "select(.\"atomic-cas\" == false)") - [[ -z "$res" ]] || echo " \"$target\"," >>"$file" -done -echo "];" >>"$file" diff --git a/crossbeam-epoch/build.rs b/crossbeam-epoch/build.rs index ac41a83da..4ef1279fc 100644 --- a/crossbeam-epoch/build.rs +++ b/crossbeam-epoch/build.rs @@ -2,7 +2,7 @@ use std::env; -include!("no_atomic_cas.rs"); +include!("no_atomic.rs"); // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -28,5 +28,5 @@ fn main() { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } - println!("cargo:rerun-if-changed=no_atomic_cas.rs"); + println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-epoch/no_atomic.rs b/crossbeam-epoch/no_atomic.rs new file mode 120000 index 000000000..417886bb7 --- /dev/null +++ b/crossbeam-epoch/no_atomic.rs @@ -0,0 +1 @@ +../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-epoch/no_atomic_cas.rs b/crossbeam-epoch/no_atomic_cas.rs deleted file mode 120000 index 3d7380fad..000000000 --- a/crossbeam-epoch/no_atomic_cas.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-epoch/src/lib.rs b/crossbeam-epoch/src/lib.rs index 8dfd5104a..ba1d3311f 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -104,10 +104,11 @@ mod primitive { pub(crate) use loom::lazy_static; pub(crate) use loom::thread_local; } +#[cfg(not(crossbeam_no_atomic_cas))] #[cfg(not(crossbeam_loom))] #[allow(unused_imports, dead_code)] mod primitive { - #[cfg(any(feature = "alloc", feature = "std"))] + #[cfg(feature = "alloc")] pub(crate) mod cell { #[derive(Debug)] #[repr(transparent)] @@ -135,14 +136,13 @@ mod primitive { } } } - #[cfg(any(feature = "alloc", feature = "std"))] + #[cfg(feature = "alloc")] pub(crate) mod sync { pub(crate) mod atomic { pub(crate) use core::sync::atomic::compiler_fence; pub(crate) use core::sync::atomic::fence; pub(crate) use core::sync::atomic::AtomicUsize; } - #[cfg(not(crossbeam_no_atomic_cas))] pub(crate) use alloc::sync::Arc; } diff --git a/crossbeam-queue/build.rs b/crossbeam-queue/build.rs index ac41a83da..4ef1279fc 100644 --- a/crossbeam-queue/build.rs +++ b/crossbeam-queue/build.rs @@ -2,7 +2,7 @@ use std::env; -include!("no_atomic_cas.rs"); +include!("no_atomic.rs"); // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -28,5 +28,5 @@ fn main() { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } - println!("cargo:rerun-if-changed=no_atomic_cas.rs"); + println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-queue/no_atomic.rs b/crossbeam-queue/no_atomic.rs new file mode 120000 index 000000000..417886bb7 --- /dev/null +++ b/crossbeam-queue/no_atomic.rs @@ -0,0 +1 @@ +../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-queue/no_atomic_cas.rs b/crossbeam-queue/no_atomic_cas.rs deleted file mode 120000 index 3d7380fad..000000000 --- a/crossbeam-queue/no_atomic_cas.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-skiplist/build.rs b/crossbeam-skiplist/build.rs index ac41a83da..4ef1279fc 100644 --- a/crossbeam-skiplist/build.rs +++ b/crossbeam-skiplist/build.rs @@ -2,7 +2,7 @@ use std::env; -include!("no_atomic_cas.rs"); +include!("no_atomic.rs"); // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -28,5 +28,5 @@ fn main() { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } - println!("cargo:rerun-if-changed=no_atomic_cas.rs"); + println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-skiplist/no_atomic.rs b/crossbeam-skiplist/no_atomic.rs new file mode 120000 index 000000000..417886bb7 --- /dev/null +++ b/crossbeam-skiplist/no_atomic.rs @@ -0,0 +1 @@ +../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-skiplist/no_atomic_cas.rs b/crossbeam-skiplist/no_atomic_cas.rs deleted file mode 120000 index 3d7380fad..000000000 --- a/crossbeam-skiplist/no_atomic_cas.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-utils/build.rs b/crossbeam-utils/build.rs index 2e7846fea..e7fabbd0c 100644 --- a/crossbeam-utils/build.rs +++ b/crossbeam-utils/build.rs @@ -4,7 +4,7 @@ use std::env; use autocfg::AutoCfg; -include!("no_atomic_cas.rs"); +include!("no_atomic.rs"); // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -29,6 +29,9 @@ fn main() { if NO_ATOMIC_CAS.contains(&&*target) { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } + if NO_ATOMIC.contains(&&*target) { + println!("cargo:rustc-cfg=crossbeam_no_atomic"); + } let cfg = match AutoCfg::new() { Ok(cfg) => cfg, @@ -47,4 +50,6 @@ fn main() { 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/no_atomic.rs b/crossbeam-utils/no_atomic.rs new file mode 120000 index 000000000..417886bb7 --- /dev/null +++ b/crossbeam-utils/no_atomic.rs @@ -0,0 +1 @@ +../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-utils/no_atomic_cas.rs b/crossbeam-utils/no_atomic_cas.rs deleted file mode 120000 index 3d7380fad..000000000 --- a/crossbeam-utils/no_atomic_cas.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-utils/src/atomic/consume.rs b/crossbeam-utils/src/atomic/consume.rs index 0fbd93e9f..f28e32bbf 100644 --- a/crossbeam-utils/src/atomic/consume.rs +++ b/crossbeam-utils/src/atomic/consume.rs @@ -1,5 +1,6 @@ #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] use crate::primitive::sync::atomic::compiler_fence; +#[cfg(not(crossbeam_no_atomic))] use core::sync::atomic::Ordering; /// Trait which allows reading from primitive atomic types with "consume" ordering. @@ -25,6 +26,7 @@ pub trait AtomicConsume { fn load_consume(&self) -> Self::Val; } +#[cfg(not(crossbeam_no_atomic))] #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] macro_rules! impl_consume { () => { @@ -37,6 +39,7 @@ macro_rules! impl_consume { }; } +#[cfg(not(crossbeam_no_atomic))] #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] macro_rules! impl_consume { () => { @@ -49,12 +52,13 @@ macro_rules! impl_consume { macro_rules! impl_atomic { ($atomic:ident, $val:ty) => { - impl AtomicConsume for ::core::sync::atomic::$atomic { + #[cfg(not(crossbeam_no_atomic))] + impl AtomicConsume for core::sync::atomic::$atomic { type Val = $val; impl_consume!(); } #[cfg(crossbeam_loom)] - impl AtomicConsume for ::loom::sync::atomic::$atomic { + impl AtomicConsume for loom::sync::atomic::$atomic { type Val = $val; impl_consume!(); } @@ -63,7 +67,6 @@ macro_rules! impl_atomic { impl_atomic!(AtomicBool, bool); impl_atomic!(AtomicUsize, usize); -#[cfg(not(crossbeam_loom))] impl_atomic!(AtomicIsize, isize); #[cfg(has_atomic_u8)] impl_atomic!(AtomicU8, u8); @@ -82,13 +85,14 @@ impl_atomic!(AtomicU64, u64); #[cfg(has_atomic_u64)] impl_atomic!(AtomicI64, i64); -impl AtomicConsume for ::core::sync::atomic::AtomicPtr { +#[cfg(not(crossbeam_no_atomic))] +impl AtomicConsume for core::sync::atomic::AtomicPtr { type Val = *mut T; impl_consume!(); } #[cfg(crossbeam_loom)] -impl AtomicConsume for ::loom::sync::atomic::AtomicPtr { +impl AtomicConsume for loom::sync::atomic::AtomicPtr { type Val = *mut T; impl_consume!(); } diff --git a/crossbeam-utils/src/atomic/mod.rs b/crossbeam-utils/src/atomic/mod.rs index 874eaf216..fc713fcac 100644 --- a/crossbeam-utils/src/atomic/mod.rs +++ b/crossbeam-utils/src/atomic/mod.rs @@ -3,11 +3,9 @@ //! * [`AtomicCell`], a thread-safe mutable memory location. //! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering. +#[cfg(not(crossbeam_no_atomic_cas))] #[cfg(not(crossbeam_loom))] -use cfg_if::cfg_if; - -#[cfg(not(crossbeam_loom))] -cfg_if! { +cfg_if::cfg_if! { // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap // around. // @@ -25,8 +23,10 @@ cfg_if! { } } +#[cfg(not(crossbeam_no_atomic_cas))] mod atomic_cell; mod consume; +#[cfg(not(crossbeam_no_atomic_cas))] pub use self::atomic_cell::AtomicCell; pub use self::consume::AtomicConsume; diff --git a/crossbeam-utils/src/lib.rs b/crossbeam-utils/src/lib.rs index a533af257..6f9df04ae 100644 --- a/crossbeam-utils/src/lib.rs +++ b/crossbeam-utils/src/lib.rs @@ -69,13 +69,18 @@ mod primitive { // use [`core::hint::spin_loop`] instead. #[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::{AtomicI64, AtomicU64}; + #[cfg(not(crossbeam_no_atomic))] #[cfg(has_atomic_u8)] pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8}; } @@ -85,15 +90,6 @@ mod primitive { } } -cfg_if! { - if #[cfg(feature = "alloc")] { - extern crate alloc; - } else if #[cfg(feature = "std")] { - extern crate std as alloc; - } -} - -#[cfg(not(crossbeam_no_atomic_cas))] pub mod atomic; mod cache_padded; diff --git a/no_atomic_cas.rs b/no_atomic.rs similarity index 53% rename from no_atomic_cas.rs rename to no_atomic.rs index 9e8fb4094..015a115ed 100644 --- a/no_atomic_cas.rs +++ b/no_atomic.rs @@ -1,4 +1,4 @@ -// This file is @generated by no_atomic_cas.sh. +// This file is @generated by no_atomic.sh. // It is not intended for manual editing. const NO_ATOMIC_CAS: &[&str] = &[ @@ -9,3 +9,10 @@ const NO_ATOMIC_CAS: &[&str] = &[ "thumbv4t-none-eabi", "thumbv6m-none-eabi", ]; +#[allow(dead_code)] +const NO_ATOMIC: &[&str] = &[ + "avr-unknown-gnu-atmega328", + "msp430-none-elf", + "riscv32i-unknown-none-elf", + "riscv32imc-unknown-none-elf", +]; diff --git a/src/lib.rs b/src/lib.rs index 6fbf4a051..9bc3ec111 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,6 @@ )] #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(not(crossbeam_no_atomic_cas))] pub use crossbeam_utils::atomic; pub mod utils {