Skip to content

Commit 9a9dd75

Browse files
bors[bot]taiki-e
andauthored
Merge #698 #704
698: Remove uses of unstable feature(cfg_target_has_atomic) r=taiki-e a=taiki-e Some no-std targets (e.g., ARMv6-M) do not support atomic CAS operations and cannot use Arc, etc. Currently, we are using an unstable feature to detect them, but it has caused breakage in the past (#435). Also, users of stable Rust are not able to compile crossbeam on those targets. Instead of depending on unstable features of the compiler, this patch detects those targets using the TARGET environment variables provided by cargo for the build script, and a list of targets that do not support atomic CAS operations. This way is the same as the way we recently adopted in [futures](rust-lang/futures-rs#2400) and [valuable](tokio-rs/valuable#12), and was originally inspired by the way [heapless](rust-embedded/heapless@44c66a7) and [defmt](https://github.com/knurling-rs/defmt/blob/963152f0fc530fca64ba4ff1492d9c4b7bf76062/build.rs#L42-L51) do, but this doesn't maintain the target list manually. (It's not really fully automated, but [it's very easy to update](https://github.com/crossbeam-rs/crossbeam/blob/a42dbed87a5739228b576f526b1e2fd80260a29b/.github/workflows/ci.yml#L89).) Also, this completely removes the dependency on unstable features from crates other than crossbeam-epoch. refs: rust-lang/rust#51953, rust-lang/futures-rs#2400, tokio-rs/valuable#12 704: Add AtomicCell::fetch_update r=taiki-e a=taiki-e Equivalent of [`std::sync::atomic::AtomicN::fetch_update`](https://doc.rust-lang.org/nightly/core/sync/atomic/struct.AtomicUsize.html#method.fetch_update) that stabilized in Rust 1.45. Co-authored-by: Taiki Endo <[email protected]>
3 parents 0e7d89a + 02a41ef + 9e5ac90 commit 9a9dd75

File tree

29 files changed

+436
-134
lines changed

29 files changed

+436
-134
lines changed

Diff for: .github/workflows/ci.yml

+20-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ jobs:
2323
name: test
2424
env:
2525
RUST_VERSION: ${{ matrix.rust }}
26-
TARGET: ${{ matrix.target }}
26+
RUST_TARGET: ${{ matrix.target }}
2727
strategy:
28+
fail-fast: false
2829
matrix:
2930
include:
3031
- rust: 1.36.0
@@ -63,6 +64,7 @@ jobs:
6364
env:
6465
RUST_VERSION: ${{ matrix.rust }}
6566
strategy:
67+
fail-fast: false
6668
matrix:
6769
rust:
6870
- 1.36.0
@@ -86,14 +88,27 @@ jobs:
8688
- name: dependency tree check
8789
run: ./ci/dependencies.sh
8890

91+
# When this job failed, run ci/no_atomic.sh and commit result changes.
92+
# TODO(taiki-e): Ideally, this should be automated using a bot that creates
93+
# PR when failed, but there is no bandwidth to implement it
94+
# right now...
95+
codegen:
96+
runs-on: ubuntu-latest
97+
steps:
98+
- uses: actions/checkout@v2
99+
- name: Install Rust
100+
run: rustup update nightly && rustup default nightly
101+
- run: ci/no_atomic.sh
102+
- run: git diff --exit-code
103+
89104
# Check formatting.
90105
rustfmt:
91106
name: rustfmt
92107
runs-on: ubuntu-latest
93108
steps:
94109
- uses: actions/checkout@v2
95110
- name: Install Rust
96-
run: rustup update stable && rustup default stable
111+
run: rustup update stable
97112
- name: rustfmt
98113
run: ./ci/rustfmt.sh
99114

@@ -104,7 +119,7 @@ jobs:
104119
steps:
105120
- uses: actions/checkout@v2
106121
- name: Install Rust
107-
run: rustup update stable && rustup default stable
122+
run: rustup update stable
108123
- name: clippy
109124
run: ./ci/clippy.sh
110125

@@ -126,7 +141,7 @@ jobs:
126141
steps:
127142
- uses: actions/checkout@v2
128143
- name: Install Rust
129-
run: rustup update stable && rustup default stable
144+
run: rustup update stable
130145
- name: loom
131146
run: ./ci/crossbeam-epoch-loom.sh
132147

@@ -154,6 +169,7 @@ jobs:
154169
- test
155170
- features
156171
- dependencies
172+
- codegen
157173
- rustfmt
158174
- clippy
159175
- san

Diff for: Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ alloc = ["crossbeam-epoch/alloc", "crossbeam-queue/alloc"]
3636

3737
# Enable to use of unstable functionality.
3838
# This is disabled by default and requires recent nightly compiler.
39-
# Note that this is outside of the normal semver guarantees and minor versions
40-
# of crossbeam may make breaking changes to them at any time.
39+
#
40+
# NOTE: This feature is outside of the normal semver guarantees and minor or
41+
# patch versions of crossbeam may make breaking changes to them at any time.
4142
nightly = ["crossbeam-epoch/nightly", "crossbeam-utils/nightly", "crossbeam-queue/nightly"]
4243

4344
[dependencies]

Diff for: ci/check-features.sh

+10-7
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ if [[ "$RUST_VERSION" != "nightly"* ]]; then
1313
# * `--no-dev-deps` - build without dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866
1414
# * `--exclude benchmarks` - benchmarks doesn't published.
1515
# * `--skip nightly` - skip `nightly` feature as requires nightly compilers.
16-
cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --skip nightly
16+
cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --skip nightly
1717
else
1818
# On nightly, all feature combinations should work.
19-
cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks
19+
cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks
2020

21-
# Check for no_std environment.
21+
# Build for no_std environment.
22+
# thumbv7m-none-eabi supports atomic CAS.
23+
# thumbv6m-none-eabi supports atomic, but not atomic CAS.
24+
# riscv32i-unknown-none-elf does not support atomic at all.
2225
rustup target add thumbv7m-none-eabi
2326
rustup target add thumbv6m-none-eabi
24-
cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv7m-none-eabi --skip std,default
25-
# * `--features nightly` is required for enable `cfg_target_has_atomic`.
26-
# * `--ignore-unknown-features` - some crates doesn't have 'nightly' feature
27-
cargo hack check --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default --features nightly --ignore-unknown-features
27+
rustup target add riscv32i-unknown-none-elf
28+
cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv7m-none-eabi --skip std,default
29+
cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target thumbv6m-none-eabi --skip std,default
30+
cargo hack build --all --feature-powerset --no-dev-deps --exclude benchmarks --target riscv32i-unknown-none-elf --skip std,default
2831
fi

Diff for: ci/no_atomic.sh

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/bash
2+
3+
# Update the list of targets that do not support atomic/CAS operations.
4+
#
5+
# Usage:
6+
# ./ci/no_atomic.sh
7+
8+
set -euo pipefail
9+
IFS=$'\n\t'
10+
11+
cd "$(cd "$(dirname "$0")" && pwd)"/..
12+
13+
file="no_atomic.rs"
14+
15+
{
16+
echo "// This file is @generated by $(basename "$0")."
17+
echo "// It is not intended for manual editing."
18+
echo ""
19+
} >"$file"
20+
21+
echo "const NO_ATOMIC_CAS: &[&str] = &[" >>"$file"
22+
for target in $(rustc --print target-list); do
23+
res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \
24+
| jq -r "select(.\"atomic-cas\" == false)")
25+
[[ -z "$res" ]] || echo " \"$target\"," >>"$file"
26+
done
27+
echo "];" >>"$file"
28+
29+
{
30+
# Only crossbeam-utils actually uses this const.
31+
echo "#[allow(dead_code)]"
32+
echo "const NO_ATOMIC_64: &[&str] = &["
33+
} >>"$file"
34+
for target in $(rustc --print target-list); do
35+
res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \
36+
| jq -r "select(.\"max-atomic-width\" == 32)")
37+
[[ -z "$res" ]] || echo " \"$target\"," >>"$file"
38+
done
39+
# It is not clear exactly what `"max-atomic-width" == null` means, but they
40+
# actually seem to have the same max-atomic-width as the target-pointer-width.
41+
# The targets currently included in this group are "mipsel-sony-psp",
42+
# "thumbv4t-none-eabi", "thumbv6m-none-eabi", all of which are
43+
# `"target-pointer-width" == "32"`, so assuming them `"max-atomic-width" == 32`
44+
# for now.
45+
for target in $(rustc --print target-list); do
46+
res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \
47+
| jq -r "select(.\"max-atomic-width\" == null)")
48+
[[ -z "$res" ]] || echo " \"$target\"," >>"$file"
49+
done
50+
echo "];" >>"$file"
51+
52+
# There is no `"max-atomic-width" == 16` or `"max-atomic-width" == 8` targets.
53+
54+
# `"max-atomic-width" == 0` means that atomic is not supported at all.
55+
{
56+
# Only crossbeam-utils actually uses this const.
57+
echo "#[allow(dead_code)]"
58+
echo "const NO_ATOMIC: &[&str] = &["
59+
} >>"$file"
60+
for target in $(rustc --print target-list); do
61+
res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \
62+
| jq -r "select(.\"max-atomic-width\" == 0)")
63+
[[ -z "$res" ]] || echo " \"$target\"," >>"$file"
64+
done
65+
echo "];" >>"$file"

Diff for: ci/test.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ set -ex
55

66
export RUSTFLAGS="-D warnings"
77

8-
if [[ -n "$TARGET" ]]; then
9-
# If TARGET is specified, use cross for testing.
8+
if [[ -n "$RUST_TARGET" ]]; then
9+
# If RUST_TARGET is specified, use cross for testing.
1010
cargo install cross
11-
cross test --all --target "$TARGET" --exclude benchmarks -- --test-threads=1
11+
cross test --all --target "$RUST_TARGET" --exclude benchmarks -- --test-threads=1
1212

1313
# For now, the non-host target only runs tests.
1414
exit 0

Diff for: crossbeam-channel/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ default = ["std"]
2020

2121
# Enable to use APIs that require `std`.
2222
# This is enabled by default.
23+
#
24+
# NOTE: Disabling `std` feature is not supported yet.
2325
std = ["crossbeam-utils/std"]
2426

2527
[dependencies]

Diff for: crossbeam-deque/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ default = ["std"]
2020

2121
# Enable to use APIs that require `std`.
2222
# This is enabled by default.
23+
#
24+
# NOTE: Disabling `std` feature is not supported yet.
2325
std = ["crossbeam-epoch/std", "crossbeam-utils/std"]
2426

2527
[dependencies]

Diff for: crossbeam-epoch/Cargo.toml

+9-6
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@ std = ["alloc", "crossbeam-utils/std", "lazy_static"]
2424

2525
# Enable to use APIs that require `alloc`.
2626
# This is enabled by default and also enabled if the `std` feature is enabled.
27+
#
28+
# NOTE: Disabling both `std` *and* `alloc` features is not supported yet.
2729
alloc = []
2830

2931
# Enable to use of unstable functionality.
3032
# This is disabled by default and requires recent nightly compiler.
31-
# Note that this is outside of the normal semver guarantees and minor versions
32-
# of crossbeam may make breaking changes to them at any time.
33+
#
34+
# NOTE: This feature is outside of the normal semver guarantees and minor or
35+
# patch versions of crossbeam may make breaking changes to them at any time.
3336
nightly = ["crossbeam-utils/nightly", "const_fn"]
3437

3538
# Enable the use of loom for concurrency testing.
3639
#
37-
# This configuration option is outside of the normal semver guarantees: minor
38-
# versions of crossbeam may make breaking changes to it at any time.
40+
# NOTE: This feature is outside of the normal semver guarantees and minor or
41+
# patch versions of crossbeam may make breaking changes to them at any time.
3942
loom = ["loom-crate", "crossbeam-utils/loom"]
4043

4144
[dependencies]
@@ -45,8 +48,8 @@ memoffset = "0.6"
4548

4649
# Enable the use of loom for concurrency testing.
4750
#
48-
# This configuration option is outside of the normal semver guarantees: minor
49-
# versions of crossbeam may make breaking changes to it at any time.
51+
# NOTE: This feature is outside of the normal semver guarantees and minor or
52+
# patch versions of crossbeam may make breaking changes to them at any time.
5053
[target.'cfg(crossbeam_loom)'.dependencies]
5154
loom-crate = { package = "loom", version = "0.5", optional = true }
5255

Diff for: crossbeam-epoch/build.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![warn(rust_2018_idioms)]
2+
3+
use std::env;
4+
5+
include!("no_atomic.rs");
6+
7+
// The rustc-cfg strings below are *not* public API. Please let us know by
8+
// opening a GitHub issue if your build environment requires some way to enable
9+
// these cfgs other than by executing our build script.
10+
fn main() {
11+
let target = match env::var("TARGET") {
12+
Ok(target) => target,
13+
Err(e) => {
14+
println!(
15+
"cargo:warning={}: unable to get TARGET environment variable: {}",
16+
env!("CARGO_PKG_NAME"),
17+
e
18+
);
19+
return;
20+
}
21+
};
22+
23+
// Note that this is `no_*`, not `has_*`. This allows treating
24+
// `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
25+
// run. This is needed for compatibility with non-cargo build systems that
26+
// don't run the build script.
27+
if NO_ATOMIC_CAS.contains(&&*target) {
28+
println!("cargo:rustc-cfg=crossbeam_no_atomic_cas");
29+
}
30+
31+
println!("cargo:rerun-if-changed=no_atomic.rs");
32+
}

Diff for: crossbeam-epoch/no_atomic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../no_atomic.rs

Diff for: crossbeam-epoch/src/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
unreachable_pub
6363
)]
6464
#![cfg_attr(not(feature = "std"), no_std)]
65-
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
6665
#![cfg_attr(feature = "nightly", feature(const_fn_trait_bound))]
6766

6867
#[cfg(crossbeam_loom)]
@@ -105,10 +104,11 @@ mod primitive {
105104
pub(crate) use loom::lazy_static;
106105
pub(crate) use loom::thread_local;
107106
}
107+
#[cfg(not(crossbeam_no_atomic_cas))]
108108
#[cfg(not(crossbeam_loom))]
109109
#[allow(unused_imports, dead_code)]
110110
mod primitive {
111-
#[cfg(any(feature = "alloc", feature = "std"))]
111+
#[cfg(feature = "alloc")]
112112
pub(crate) mod cell {
113113
#[derive(Debug)]
114114
#[repr(transparent)]
@@ -136,14 +136,13 @@ mod primitive {
136136
}
137137
}
138138
}
139-
#[cfg(any(feature = "alloc", feature = "std"))]
139+
#[cfg(feature = "alloc")]
140140
pub(crate) mod sync {
141141
pub(crate) mod atomic {
142142
pub(crate) use core::sync::atomic::compiler_fence;
143143
pub(crate) use core::sync::atomic::fence;
144144
pub(crate) use core::sync::atomic::AtomicUsize;
145145
}
146-
#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
147146
pub(crate) use alloc::sync::Arc;
148147
}
149148

@@ -154,7 +153,7 @@ mod primitive {
154153
pub(crate) use lazy_static::lazy_static;
155154
}
156155

157-
#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
156+
#[cfg(not(crossbeam_no_atomic_cas))]
158157
cfg_if! {
159158
if #[cfg(feature = "alloc")] {
160159
extern crate alloc;

Diff for: crossbeam-queue/Cargo.toml

+7-2
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ std = ["alloc", "crossbeam-utils/std"]
2424

2525
# Enable to use APIs that require `alloc`.
2626
# This is enabled by default and also enabled if the `std` feature is enabled.
27+
#
28+
# NOTE: Disabling both `std` *and* `alloc` features is not supported yet.
2729
alloc = []
2830

31+
# These features are no longer used.
32+
# TODO: remove in the next major version.
2933
# Enable to use of unstable functionality.
3034
# This is disabled by default and requires recent nightly compiler.
31-
# Note that this is outside of the normal semver guarantees and minor versions
32-
# of crossbeam may make breaking changes to them at any time.
35+
#
36+
# NOTE: This feature is outside of the normal semver guarantees and minor or
37+
# patch versions of crossbeam may make breaking changes to them at any time.
3338
nightly = ["crossbeam-utils/nightly"]
3439

3540
[dependencies]

Diff for: crossbeam-queue/build.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![warn(rust_2018_idioms)]
2+
3+
use std::env;
4+
5+
include!("no_atomic.rs");
6+
7+
// The rustc-cfg strings below are *not* public API. Please let us know by
8+
// opening a GitHub issue if your build environment requires some way to enable
9+
// these cfgs other than by executing our build script.
10+
fn main() {
11+
let target = match env::var("TARGET") {
12+
Ok(target) => target,
13+
Err(e) => {
14+
println!(
15+
"cargo:warning={}: unable to get TARGET environment variable: {}",
16+
env!("CARGO_PKG_NAME"),
17+
e
18+
);
19+
return;
20+
}
21+
};
22+
23+
// Note that this is `no_*`, not `has_*`. This allows treating
24+
// `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
25+
// run. This is needed for compatibility with non-cargo build systems that
26+
// don't run the build script.
27+
if NO_ATOMIC_CAS.contains(&&*target) {
28+
println!("cargo:rustc-cfg=crossbeam_no_atomic_cas");
29+
}
30+
31+
println!("cargo:rerun-if-changed=no_atomic.rs");
32+
}

Diff for: crossbeam-queue/no_atomic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../no_atomic.rs

Diff for: crossbeam-queue/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@
1919
unreachable_pub
2020
)]
2121
#![cfg_attr(not(feature = "std"), no_std)]
22-
#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
2322

24-
#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
23+
#[cfg(not(crossbeam_no_atomic_cas))]
2524
cfg_if::cfg_if! {
2625
if #[cfg(feature = "alloc")] {
2726
extern crate alloc;

0 commit comments

Comments
 (0)