Skip to content

Commit

Permalink
Allow AtomicConsume to be used on targets that do not support atomic
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed May 23, 2021
1 parent 6d9227c commit 138c956
Show file tree
Hide file tree
Showing 23 changed files with 97 additions and 100 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -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...
Expand All @@ -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.
Expand Down
32 changes: 0 additions & 32 deletions build.rs

This file was deleted.

15 changes: 10 additions & 5 deletions ci/check-features.sh
Expand Up @@ -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
40 changes: 40 additions & 0 deletions 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"
27 changes: 0 additions & 27 deletions ci/no_atomic_cas.sh

This file was deleted.

4 changes: 2 additions & 2 deletions crossbeam-epoch/build.rs
Expand Up @@ -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
Expand All @@ -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");
}
1 change: 1 addition & 0 deletions crossbeam-epoch/no_atomic.rs
1 change: 0 additions & 1 deletion crossbeam-epoch/no_atomic_cas.rs

This file was deleted.

6 changes: 3 additions & 3 deletions crossbeam-epoch/src/lib.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions crossbeam-queue/build.rs
Expand Up @@ -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
Expand All @@ -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");
}
1 change: 1 addition & 0 deletions crossbeam-queue/no_atomic.rs
1 change: 0 additions & 1 deletion crossbeam-queue/no_atomic_cas.rs

This file was deleted.

4 changes: 2 additions & 2 deletions crossbeam-skiplist/build.rs
Expand Up @@ -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
Expand All @@ -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");
}
1 change: 1 addition & 0 deletions crossbeam-skiplist/no_atomic.rs
1 change: 0 additions & 1 deletion crossbeam-skiplist/no_atomic_cas.rs

This file was deleted.

7 changes: 6 additions & 1 deletion crossbeam-utils/build.rs
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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");
}
1 change: 1 addition & 0 deletions crossbeam-utils/no_atomic.rs
1 change: 0 additions & 1 deletion crossbeam-utils/no_atomic_cas.rs

This file was deleted.

14 changes: 9 additions & 5 deletions 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.
Expand All @@ -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 {
() => {
Expand All @@ -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 {
() => {
Expand All @@ -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!();
}
Expand All @@ -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);
Expand All @@ -82,13 +85,14 @@ impl_atomic!(AtomicU64, u64);
#[cfg(has_atomic_u64)]
impl_atomic!(AtomicI64, i64);

impl<T> AtomicConsume for ::core::sync::atomic::AtomicPtr<T> {
#[cfg(not(crossbeam_no_atomic))]
impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}

#[cfg(crossbeam_loom)]
impl<T> AtomicConsume for ::loom::sync::atomic::AtomicPtr<T> {
impl<T> AtomicConsume for loom::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}
8 changes: 4 additions & 4 deletions crossbeam-utils/src/atomic/mod.rs
Expand Up @@ -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.
//
Expand All @@ -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;
14 changes: 5 additions & 9 deletions crossbeam-utils/src/lib.rs
Expand Up @@ -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};
}
Expand All @@ -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;
Expand Down

0 comments on commit 138c956

Please sign in to comment.