From 558c3ced61ef1f3bece2ab1de0a65547b906d679 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 17 May 2021 23:36:45 +0900 Subject: [PATCH 1/3] Remove uses of unstable feature(cfg_target_has_atomic) --- .github/workflows/ci.yml | 20 +++++++++++++++--- Cargo.toml | 5 +++-- build.rs | 32 +++++++++++++++++++++++++++++ ci/check-features.sh | 4 +--- ci/no_atomic_cas.sh | 27 ++++++++++++++++++++++++ crossbeam-channel/Cargo.toml | 2 ++ crossbeam-deque/Cargo.toml | 2 ++ crossbeam-epoch/Cargo.toml | 15 ++++++++------ crossbeam-epoch/build.rs | 32 +++++++++++++++++++++++++++++ crossbeam-epoch/no_atomic_cas.rs | 1 + crossbeam-epoch/src/lib.rs | 5 ++--- crossbeam-queue/Cargo.toml | 9 ++++++-- crossbeam-queue/build.rs | 32 +++++++++++++++++++++++++++++ crossbeam-queue/no_atomic_cas.rs | 1 + crossbeam-queue/src/lib.rs | 3 +-- crossbeam-skiplist/Cargo.toml | 8 ++------ crossbeam-skiplist/build.rs | 32 +++++++++++++++++++++++++++++ crossbeam-skiplist/no_atomic_cas.rs | 1 + crossbeam-skiplist/src/lib.rs | 3 +-- crossbeam-utils/Cargo.toml | 11 ++++++---- crossbeam-utils/build.rs | 29 +++++++++++++++++++++++++- crossbeam-utils/no_atomic_cas.rs | 1 + crossbeam-utils/src/lib.rs | 3 +-- no_atomic_cas.rs | 11 ++++++++++ src/lib.rs | 3 +-- 25 files changed, 254 insertions(+), 38 deletions(-) create mode 100644 build.rs create mode 100755 ci/no_atomic_cas.sh create mode 100644 crossbeam-epoch/build.rs create mode 120000 crossbeam-epoch/no_atomic_cas.rs create mode 100644 crossbeam-queue/build.rs create mode 120000 crossbeam-queue/no_atomic_cas.rs create mode 100644 crossbeam-skiplist/build.rs create mode 120000 crossbeam-skiplist/no_atomic_cas.rs create mode 120000 crossbeam-utils/no_atomic_cas.rs create mode 100644 no_atomic_cas.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ceb50f57..671bada09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,6 +86,19 @@ jobs: - name: dependency tree check run: ./ci/dependencies.sh + # When this job failed, run ci/no_atomic_cas.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... + codegen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update nightly && rustup default nightly + - run: ci/no_atomic_cas.sh + - run: git diff --exit-code + # Check formatting. rustfmt: name: rustfmt @@ -93,7 +106,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install Rust - run: rustup update stable && rustup default stable + run: rustup update stable - name: rustfmt run: ./ci/rustfmt.sh @@ -104,7 +117,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install Rust - run: rustup update stable && rustup default stable + run: rustup update stable - name: clippy run: ./ci/clippy.sh @@ -126,7 +139,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install Rust - run: rustup update stable && rustup default stable + run: rustup update stable - name: loom run: ./ci/crossbeam-epoch-loom.sh @@ -154,6 +167,7 @@ jobs: - test - features - dependencies + - codegen - rustfmt - clippy - san diff --git a/Cargo.toml b/Cargo.toml index 4389b7931..1a490e5ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,9 @@ alloc = ["crossbeam-epoch/alloc", "crossbeam-queue/alloc"] # Enable to use of unstable functionality. # This is disabled by default and requires recent nightly compiler. -# Note that this is outside of the normal semver guarantees and minor versions -# of crossbeam may make breaking changes to them at any time. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. nightly = ["crossbeam-epoch/nightly", "crossbeam-utils/nightly", "crossbeam-queue/nightly"] [dependencies] diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..ac41a83da --- /dev/null +++ b/build.rs @@ -0,0 +1,32 @@ +#![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 1eeddc520..c6901d0b7 100755 --- a/ci/check-features.sh +++ b/ci/check-features.sh @@ -22,7 +22,5 @@ else 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 - # * `--features nightly` is required for enable `cfg_target_has_atomic`. - # * `--ignore-unknown-features` - some crates doesn't have 'nightly' feature - cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default --features nightly --ignore-unknown-features + cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default fi diff --git a/ci/no_atomic_cas.sh b/ci/no_atomic_cas.sh new file mode 100755 index 000000000..bc2e3500f --- /dev/null +++ b/ci/no_atomic_cas.sh @@ -0,0 +1,27 @@ +#!/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-channel/Cargo.toml b/crossbeam-channel/Cargo.toml index 0e048a262..c2812fef4 100644 --- a/crossbeam-channel/Cargo.toml +++ b/crossbeam-channel/Cargo.toml @@ -20,6 +20,8 @@ default = ["std"] # Enable to use APIs that require `std`. # This is enabled by default. +# +# NOTE: Disabling `std` feature is not supported yet. std = ["crossbeam-utils/std"] [dependencies] diff --git a/crossbeam-deque/Cargo.toml b/crossbeam-deque/Cargo.toml index 55e22351b..cba710e74 100644 --- a/crossbeam-deque/Cargo.toml +++ b/crossbeam-deque/Cargo.toml @@ -20,6 +20,8 @@ default = ["std"] # Enable to use APIs that require `std`. # This is enabled by default. +# +# NOTE: Disabling `std` feature is not supported yet. std = ["crossbeam-epoch/std", "crossbeam-utils/std"] [dependencies] diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index de70ebb87..18154259b 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -24,18 +24,21 @@ std = ["alloc", "crossbeam-utils/std", "lazy_static"] # Enable to use APIs that require `alloc`. # This is enabled by default and also enabled if the `std` feature is enabled. +# +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. alloc = [] # Enable to use of unstable functionality. # This is disabled by default and requires recent nightly compiler. -# Note that this is outside of the normal semver guarantees and minor versions -# of crossbeam may make breaking changes to them at any time. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. nightly = ["crossbeam-utils/nightly", "const_fn"] # Enable the use of loom for concurrency testing. # -# This configuration option is outside of the normal semver guarantees: minor -# versions of crossbeam may make breaking changes to it at any time. +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. loom = ["loom-crate", "crossbeam-utils/loom"] [dependencies] @@ -45,8 +48,8 @@ memoffset = "0.6" # Enable the use of loom for concurrency testing. # -# This configuration option is outside of the normal semver guarantees: minor -# versions of crossbeam may make breaking changes to it at any time. +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. [target.'cfg(crossbeam_loom)'.dependencies] loom-crate = { package = "loom", version = "0.5", optional = true } diff --git a/crossbeam-epoch/build.rs b/crossbeam-epoch/build.rs new file mode 100644 index 000000000..ac41a83da --- /dev/null +++ b/crossbeam-epoch/build.rs @@ -0,0 +1,32 @@ +#![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/crossbeam-epoch/no_atomic_cas.rs b/crossbeam-epoch/no_atomic_cas.rs new file mode 120000 index 000000000..3d7380fad --- /dev/null +++ b/crossbeam-epoch/no_atomic_cas.rs @@ -0,0 +1 @@ +../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 81b6b37c9..8dfd5104a 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -62,7 +62,6 @@ unreachable_pub )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))] #![cfg_attr(feature = "nightly", feature(const_fn_trait_bound))] #[cfg(crossbeam_loom)] @@ -143,7 +142,7 @@ mod primitive { pub(crate) use core::sync::atomic::fence; pub(crate) use core::sync::atomic::AtomicUsize; } - #[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] + #[cfg(not(crossbeam_no_atomic_cas))] pub(crate) use alloc::sync::Arc; } @@ -154,7 +153,7 @@ mod primitive { pub(crate) use lazy_static::lazy_static; } -#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] +#[cfg(not(crossbeam_no_atomic_cas))] cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-queue/Cargo.toml b/crossbeam-queue/Cargo.toml index 622536eb8..b79778d83 100644 --- a/crossbeam-queue/Cargo.toml +++ b/crossbeam-queue/Cargo.toml @@ -24,12 +24,17 @@ std = ["alloc", "crossbeam-utils/std"] # Enable to use APIs that require `alloc`. # This is enabled by default and also enabled if the `std` feature is enabled. +# +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. alloc = [] +# These features are no longer used. +# TODO: remove in the next major version. # Enable to use of unstable functionality. # This is disabled by default and requires recent nightly compiler. -# Note that this is outside of the normal semver guarantees and minor versions -# of crossbeam may make breaking changes to them at any time. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. nightly = ["crossbeam-utils/nightly"] [dependencies] diff --git a/crossbeam-queue/build.rs b/crossbeam-queue/build.rs new file mode 100644 index 000000000..ac41a83da --- /dev/null +++ b/crossbeam-queue/build.rs @@ -0,0 +1,32 @@ +#![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/crossbeam-queue/no_atomic_cas.rs b/crossbeam-queue/no_atomic_cas.rs new file mode 120000 index 000000000..3d7380fad --- /dev/null +++ b/crossbeam-queue/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-queue/src/lib.rs b/crossbeam-queue/src/lib.rs index cba6416f6..846d7c2e1 100644 --- a/crossbeam-queue/src/lib.rs +++ b/crossbeam-queue/src/lib.rs @@ -19,9 +19,8 @@ unreachable_pub )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))] -#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] +#[cfg(not(crossbeam_no_atomic_cas))] cfg_if::cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-skiplist/Cargo.toml b/crossbeam-skiplist/Cargo.toml index f6c46efaa..beae558d9 100644 --- a/crossbeam-skiplist/Cargo.toml +++ b/crossbeam-skiplist/Cargo.toml @@ -24,14 +24,10 @@ std = ["alloc", "crossbeam-epoch/std", "crossbeam-utils/std"] # Enable to use APIs that require `alloc`. # This is enabled by default and also enabled if the `std` feature is enabled. +# +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. alloc = ["crossbeam-epoch/alloc"] -# Enable to use of unstable functionality. -# This is disabled by default and requires recent nightly compiler. -# Note that this is outside of the normal semver guarantees and minor versions -# of crossbeam may make breaking changes to them at any time. -nightly = ["crossbeam-epoch/nightly", "crossbeam-utils/nightly"] - [dependencies] cfg-if = "1" diff --git a/crossbeam-skiplist/build.rs b/crossbeam-skiplist/build.rs new file mode 100644 index 000000000..ac41a83da --- /dev/null +++ b/crossbeam-skiplist/build.rs @@ -0,0 +1,32 @@ +#![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/crossbeam-skiplist/no_atomic_cas.rs b/crossbeam-skiplist/no_atomic_cas.rs new file mode 120000 index 000000000..3d7380fad --- /dev/null +++ b/crossbeam-skiplist/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-skiplist/src/lib.rs b/crossbeam-skiplist/src/lib.rs index 13988fa32..cb5f0462d 100644 --- a/crossbeam-skiplist/src/lib.rs +++ b/crossbeam-skiplist/src/lib.rs @@ -242,11 +242,10 @@ unreachable_pub )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))] use cfg_if::cfg_if; -#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] +#[cfg(not(crossbeam_no_atomic_cas))] cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 4962b7141..212671e59 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -22,10 +22,13 @@ default = ["std"] # This is enabled by default. std = ["lazy_static"] +# These features are no longer used. +# TODO: remove in the next major version. # Enable to use of unstable functionality. # This is disabled by default and requires recent nightly compiler. -# Note that this is outside of the normal semver guarantees and minor versions -# of crossbeam may make breaking changes to them at any time. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. nightly = [] [dependencies] @@ -34,8 +37,8 @@ lazy_static = { version = "1.4.0", optional = true } # Enable the use of loom for concurrency testing. # -# This configuration option is outside of the normal semver guarantees: minor -# versions of crossbeam may make breaking changes to it at any time. +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. [target.'cfg(crossbeam_loom)'.dependencies] loom = { version = "0.5", optional = true } diff --git a/crossbeam-utils/build.rs b/crossbeam-utils/build.rs index 3e5102183..2e7846fea 100644 --- a/crossbeam-utils/build.rs +++ b/crossbeam-utils/build.rs @@ -1,14 +1,41 @@ +#![warn(rust_2018_idioms)] + +use std::env; + use autocfg::AutoCfg; +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"); + } + let cfg = match AutoCfg::new() { Ok(cfg) => cfg, Err(e) => { println!( - "cargo:warning=crossbeam-utils: unable to determine rustc version: {}", + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), e ); return; diff --git a/crossbeam-utils/no_atomic_cas.rs b/crossbeam-utils/no_atomic_cas.rs new file mode 120000 index 000000000..3d7380fad --- /dev/null +++ b/crossbeam-utils/no_atomic_cas.rs @@ -0,0 +1 @@ +../no_atomic_cas.rs \ No newline at end of file diff --git a/crossbeam-utils/src/lib.rs b/crossbeam-utils/src/lib.rs index 880d37ec6..a533af257 100644 --- a/crossbeam-utils/src/lib.rs +++ b/crossbeam-utils/src/lib.rs @@ -38,7 +38,6 @@ unreachable_pub )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))] #[cfg(crossbeam_loom)] #[allow(unused_imports)] @@ -94,7 +93,7 @@ cfg_if! { } } -#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] +#[cfg(not(crossbeam_no_atomic_cas))] pub mod atomic; mod cache_padded; diff --git a/no_atomic_cas.rs b/no_atomic_cas.rs new file mode 100644 index 000000000..9e8fb4094 --- /dev/null +++ b/no_atomic_cas.rs @@ -0,0 +1,11 @@ +// This file is @generated by no_atomic_cas.sh. +// It is not intended for manual editing. + +const NO_ATOMIC_CAS: &[&str] = &[ + "avr-unknown-gnu-atmega328", + "msp430-none-elf", + "riscv32i-unknown-none-elf", + "riscv32imc-unknown-none-elf", + "thumbv4t-none-eabi", + "thumbv6m-none-eabi", +]; diff --git a/src/lib.rs b/src/lib.rs index 9d7d37416..6fbf4a051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,9 +52,8 @@ unreachable_pub )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))] -#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))] +#[cfg(not(crossbeam_no_atomic_cas))] pub use crossbeam_utils::atomic; pub mod utils { From 7e6c09783123bf9019d9cebc2a44d24c7239b5e7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 23 May 2021 13:55:53 +0900 Subject: [PATCH 2/3] 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 671bada09..a7c312d3d 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 { From 02a41ef8ba0ffa8c72a3752860f5d30b178fc303 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 27 May 2021 22:32:42 +0900 Subject: [PATCH 3/3] 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 | 45 +++++++------------ crossbeam-utils/src/atomic/consume.rs | 10 +---- crossbeam-utils/src/lib.rs | 20 +++------ crossbeam-utils/tests/atomic_cell.rs | 54 ++++++++++++++++++----- no_atomic.rs | 41 +++++++++++++++++ 10 files changed, 144 insertions(+), 89 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..e1771382b 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -497,33 +497,25 @@ 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, atomic::AtomicUsize, "let a = AtomicCell::new(7usize);" ); -#[cfg(not(crossbeam_loom))] impl_arithmetic!( isize, atomic::AtomicIsize, @@ -809,16 +801,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 +820,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..28208ee76 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,47 @@ 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!(any( + target_pointer_width = "64", + target_pointer_width = "128" + )) + ); + 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",