From efea54ed8642ad32f3e920611ed06ab0ee068e6d Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 17 Jun 2023 20:48:59 +0900 Subject: [PATCH 01/25] Always use load(Acquire) for load_consume on Miri/TSan --- crossbeam-epoch/build.rs | 4 ++-- crossbeam-queue/build.rs | 4 ++-- crossbeam-skiplist/build.rs | 4 ++-- crossbeam-utils/build.rs | 8 +++++++- crossbeam-utils/src/atomic/consume.rs | 15 +++++++++++---- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/crossbeam-epoch/build.rs b/crossbeam-epoch/build.rs index 978141aa5..86c3b6ff7 100644 --- a/crossbeam-epoch/build.rs +++ b/crossbeam-epoch/build.rs @@ -18,6 +18,8 @@ include!("no_atomic.rs"); include!("build-common.rs"); fn main() { + println!("cargo:rerun-if-changed=no_atomic.rs"); + let target = match env::var("TARGET") { Ok(target) => convert_custom_linux_target(target), Err(e) => { @@ -52,6 +54,4 @@ fn main() { if !cfg.probe_rustc_version(1, 61) { println!("cargo:rustc-cfg=crossbeam_no_const_fn_trait_bound"); } - - println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-queue/build.rs b/crossbeam-queue/build.rs index 6975dd8c2..ffa02a663 100644 --- a/crossbeam-queue/build.rs +++ b/crossbeam-queue/build.rs @@ -18,6 +18,8 @@ include!("no_atomic.rs"); include!("build-common.rs"); fn main() { + println!("cargo:rerun-if-changed=no_atomic.rs"); + let target = match env::var("TARGET") { Ok(target) => convert_custom_linux_target(target), Err(e) => { @@ -36,6 +38,4 @@ fn main() { if NO_ATOMIC_CAS.contains(&&*target) { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } - - println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-skiplist/build.rs b/crossbeam-skiplist/build.rs index 6975dd8c2..ffa02a663 100644 --- a/crossbeam-skiplist/build.rs +++ b/crossbeam-skiplist/build.rs @@ -18,6 +18,8 @@ include!("no_atomic.rs"); include!("build-common.rs"); fn main() { + println!("cargo:rerun-if-changed=no_atomic.rs"); + let target = match env::var("TARGET") { Ok(target) => convert_custom_linux_target(target), Err(e) => { @@ -36,6 +38,4 @@ fn main() { if NO_ATOMIC_CAS.contains(&&*target) { println!("cargo:rustc-cfg=crossbeam_no_atomic_cas"); } - - println!("cargo:rerun-if-changed=no_atomic.rs"); } diff --git a/crossbeam-utils/build.rs b/crossbeam-utils/build.rs index 617162fb5..39785f030 100644 --- a/crossbeam-utils/build.rs +++ b/crossbeam-utils/build.rs @@ -30,6 +30,8 @@ include!("no_atomic.rs"); include!("build-common.rs"); fn main() { + println!("cargo:rerun-if-changed=no_atomic.rs"); + let target = match env::var("TARGET") { Ok(target) => convert_custom_linux_target(target), Err(e) => { @@ -57,5 +59,9 @@ fn main() { // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`. } - println!("cargo:rerun-if-changed=no_atomic.rs"); + // `cfg(sanitize = "..")` is not stabilized. + let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); + if sanitize.contains("thread") { + println!("cargo:rustc-cfg=crossbeam_sanitize_thread"); + } } diff --git a/crossbeam-utils/src/atomic/consume.rs b/crossbeam-utils/src/atomic/consume.rs index 277b370a5..862e128c9 100644 --- a/crossbeam-utils/src/atomic/consume.rs +++ b/crossbeam-utils/src/atomic/consume.rs @@ -1,5 +1,3 @@ -#[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; @@ -27,11 +25,17 @@ pub trait AtomicConsume { } #[cfg(not(crossbeam_no_atomic))] -#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] +// Miri doesn't support "consume" ordering and ThreadSanitizer doesn't treat +// load(Relaxed) + compiler_fence(Acquire) as "consume" load. +#[cfg(all( + any(target_arch = "arm", target_arch = "aarch64"), + not(any(miri, crossbeam_sanitize_thread)), +))] macro_rules! impl_consume { () => { #[inline] fn load_consume(&self) -> Self::Val { + use crate::primitive::sync::atomic::compiler_fence; let result = self.load(Ordering::Relaxed); compiler_fence(Ordering::Acquire); result @@ -40,7 +44,10 @@ macro_rules! impl_consume { } #[cfg(not(crossbeam_no_atomic))] -#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] +#[cfg(not(all( + any(target_arch = "arm", target_arch = "aarch64"), + not(any(miri, crossbeam_sanitize_thread)), +)))] macro_rules! impl_consume { () => { #[inline] From 96e457564f8eda7cbec2d0b1b8a2cda076a86869 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 16 Jul 2023 14:31:08 +0900 Subject: [PATCH 02/25] ci: Use armv5te instead of mips to test target that does not have 64-bit atomics --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99449182c..91e729c5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: # Test 32-bit target that does not have AtomicU64/AtomicI64. - rust: nightly os: ubuntu-latest - target: mips-unknown-linux-gnu + target: armv5te-unknown-linux-gnueabi runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 From 064bc05c7e11e83d54f00425e2619442104abe2d Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 16 Jul 2023 14:42:51 +0900 Subject: [PATCH 03/25] Fix clippy::incorrect_clone_impl_on_copy_type warning ``` error: incorrect implementation of `clone` on a `Copy` type --> crossbeam-epoch/src/atomic.rs:1171:29 | 1171 | fn clone(&self) -> Self { | _____________________________^ 1172 | | Self { 1173 | | data: self.data, 1174 | | _marker: PhantomData, 1175 | | } 1176 | | } | |_____^ help: change this to: `{ *self }` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default error: incorrect implementation of `clone` on a `Copy` type --> crossbeam-deque/src/deque.rs:82:34 | 82 | fn clone(&self) -> Buffer { | __________________________________^ 83 | | Buffer { 84 | | ptr: self.ptr, 85 | | cap: self.cap, 86 | | } 87 | | } | |_____^ help: change this to: `{ *self }` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default ``` --- crossbeam-deque/src/deque.rs | 5 +---- crossbeam-epoch/src/atomic.rs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/crossbeam-deque/src/deque.rs b/crossbeam-deque/src/deque.rs index 8afe15f4b..c37de2dee 100644 --- a/crossbeam-deque/src/deque.rs +++ b/crossbeam-deque/src/deque.rs @@ -80,10 +80,7 @@ impl Buffer { impl Clone for Buffer { fn clone(&self) -> Buffer { - Buffer { - ptr: self.ptr, - cap: self.cap, - } + *self } } diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 19bab4729..0eb041494 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -1313,10 +1313,7 @@ pub struct Shared<'g, T: 'g + ?Sized + Pointable> { impl Clone for Shared<'_, T> { fn clone(&self) -> Self { - Self { - data: self.data, - _marker: PhantomData, - } + *self } } From 507497680666be4b35bf841a46a79530b228cf40 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 16 Jul 2023 15:20:09 +0900 Subject: [PATCH 04/25] Update loom to 0.6 --- crossbeam-epoch/Cargo.toml | 2 +- crossbeam-utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 50ec66e9e..2a6d58561 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -55,7 +55,7 @@ scopeguard = { version = "1.1", default-features = false } # 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 } +loom-crate = { package = "loom", version = "0.6", optional = true } [dependencies.crossbeam-utils] version = "0.8.5" diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index dc4a25ba4..1f98235ca 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -38,7 +38,7 @@ cfg-if = "1" # 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 } +loom = { version = "0.6", optional = true } [dev-dependencies] rand = "0.8" From 8f585d6237d06feae1c668636f0629cfe9b6085e Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 16 Jul 2023 15:31:35 +0900 Subject: [PATCH 05/25] Always use load(Acquire) for load_consume on loom --- crossbeam-utils/src/atomic/consume.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crossbeam-utils/src/atomic/consume.rs b/crossbeam-utils/src/atomic/consume.rs index 862e128c9..80a88829b 100644 --- a/crossbeam-utils/src/atomic/consume.rs +++ b/crossbeam-utils/src/atomic/consume.rs @@ -25,11 +25,15 @@ pub trait AtomicConsume { } #[cfg(not(crossbeam_no_atomic))] -// Miri doesn't support "consume" ordering and ThreadSanitizer doesn't treat +// Miri and Loom don't support "consume" ordering and ThreadSanitizer doesn't treat // load(Relaxed) + compiler_fence(Acquire) as "consume" load. +// LLVM generates machine code equivalent to fence(Acquire) in compiler_fence(Acquire) +// on PowerPC, MIPS, etc. (https://godbolt.org/z/hffvjvW7h), so for now the fence +// can be actually avoided here only on ARM and AArch64. See also +// https://github.com/rust-lang/rust/issues/62256. #[cfg(all( any(target_arch = "arm", target_arch = "aarch64"), - not(any(miri, crossbeam_sanitize_thread)), + not(any(miri, crossbeam_loom, crossbeam_sanitize_thread)), ))] macro_rules! impl_consume { () => { @@ -46,7 +50,7 @@ macro_rules! impl_consume { #[cfg(not(crossbeam_no_atomic))] #[cfg(not(all( any(target_arch = "arm", target_arch = "aarch64"), - not(any(miri, crossbeam_sanitize_thread)), + not(any(miri, crossbeam_loom, crossbeam_sanitize_thread)), )))] macro_rules! impl_consume { () => { From d8c4d5bb7fc9f93381b7aa67ed8dcb66fb793f28 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Thu, 27 Jul 2023 22:26:13 +0200 Subject: [PATCH 06/25] Remove timing assumptions from `wait_and_drop` test (#1005) --- crossbeam-utils/tests/wait_group.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crossbeam-utils/tests/wait_group.rs b/crossbeam-utils/tests/wait_group.rs index 0ec4a729c..5b549b849 100644 --- a/crossbeam-utils/tests/wait_group.rs +++ b/crossbeam-utils/tests/wait_group.rs @@ -36,25 +36,27 @@ fn wait() { } #[test] -#[cfg_attr(miri, ignore)] // this test makes timing assumptions, but Miri is so slow it violates them fn wait_and_drop() { let wg = WaitGroup::new(); + let wg2 = WaitGroup::new(); let (tx, rx) = mpsc::channel(); for _ in 0..THREADS { let wg = wg.clone(); + let wg2 = wg2.clone(); let tx = tx.clone(); thread::spawn(move || { - thread::sleep(Duration::from_millis(100)); + wg2.wait(); tx.send(()).unwrap(); drop(wg); }); } - // At this point, all spawned threads should be in `thread::sleep`, so we shouldn't get anything - // from the channel. + // At this point, no thread has gotten past `wg2.wait()`, so we shouldn't get anything from the + // channel. assert!(rx.try_recv().is_err()); + drop(wg2); wg.wait(); From 9fc2cf1ffb0754cb5a9f06599dff3da80aba1d1d Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 5 Aug 2023 16:36:47 +0900 Subject: [PATCH 07/25] Fix noop_method_call warning in doctest ``` error: call to `.clone()` on a reference in this situation does nothing --> crossbeam-epoch/src/guard.rs:451:38 | 14 | let dummy = &epoch::unprotected().clone(); | ^^^^^^^^ help: remove this redundant call | = note: the type `Guard` does not implement `Clone`, so calling `clone` on `&Guard` copies the reference, which does not do anything and can be removed note: the lint level is defined here --> crossbeam-epoch/src/guard.rs:438:9 | 1 | #![deny(warnings, rust_2018_idioms)] | ^^^^^^^^ = note: `#[deny(noop_method_call)]` implied by `#[deny(warnings)]` ``` --- crossbeam-epoch/src/guard.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crossbeam-epoch/src/guard.rs b/crossbeam-epoch/src/guard.rs index ba7fe1b11..da1c5c01b 100644 --- a/crossbeam-epoch/src/guard.rs +++ b/crossbeam-epoch/src/guard.rs @@ -447,8 +447,8 @@ impl fmt::Debug for Guard { /// // Load `a` without pinning the current thread. /// a.load(Relaxed, epoch::unprotected()); /// -/// // It's possible to create more dummy guards by calling `clone()`. -/// let dummy = &epoch::unprotected().clone(); +/// // It's possible to create more dummy guards. +/// let dummy = epoch::unprotected(); /// /// dummy.defer(move || { /// println!("This gets executed immediately."); From a076656c5ae5a6f10958031a99865d8c51400014 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 9 Aug 2023 18:24:19 +0900 Subject: [PATCH 08/25] Update loom to 0.7 --- crossbeam-epoch/Cargo.toml | 2 +- crossbeam-epoch/src/lib.rs | 10 +++------- crossbeam-utils/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 2a6d58561..651f3698a 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -55,7 +55,7 @@ scopeguard = { version = "1.1", default-features = false } # 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.6", optional = true } +loom-crate = { package = "loom", version = "0.7", optional = true } [dependencies.crossbeam-utils] version = "0.8.5" diff --git a/crossbeam-epoch/src/lib.rs b/crossbeam-epoch/src/lib.rs index b432c1f40..94d5db1bc 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -76,8 +76,7 @@ mod primitive { } pub(crate) mod sync { pub(crate) mod atomic { - use core::sync::atomic::Ordering; - pub(crate) use loom::sync::atomic::{fence, AtomicUsize}; + pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize}; // FIXME: loom does not support compiler_fence at the moment. // https://github.com/tokio-rs/loom/issues/117 @@ -94,7 +93,6 @@ mod primitive { #[cfg(not(crossbeam_loom))] #[allow(unused_imports, dead_code)] mod primitive { - #[cfg(feature = "alloc")] pub(crate) mod cell { #[derive(Debug)] #[repr(transparent)] @@ -122,13 +120,11 @@ mod primitive { } } } - #[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; + pub(crate) use core::sync::atomic::{compiler_fence, fence, AtomicPtr, AtomicUsize}; } + #[cfg(feature = "alloc")] pub(crate) use alloc::sync::Arc; } diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 1f98235ca..2258552f8 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -38,7 +38,7 @@ cfg-if = "1" # 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.6", optional = true } +loom = { version = "0.7", optional = true } [dev-dependencies] rand = "0.8" From 76f608cd40191a1e5d8290ce5e70fd0503bae6e2 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 12 Aug 2023 05:09:40 +0900 Subject: [PATCH 09/25] CachePadded: update alignment for mips32r6 and mips64r6 --- crossbeam-utils/src/cache_padded.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crossbeam-utils/src/cache_padded.rs b/crossbeam-utils/src/cache_padded.rs index 7fce7cc1b..4978a3eb3 100644 --- a/crossbeam-utils/src/cache_padded.rs +++ b/crossbeam-utils/src/cache_padded.rs @@ -100,7 +100,9 @@ use core::ops::{Deref, DerefMut}; any( target_arch = "arm", target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "riscv32", target_arch = "riscv64", target_arch = "sparc", @@ -134,7 +136,9 @@ use core::ops::{Deref, DerefMut}; target_arch = "powerpc64", target_arch = "arm", target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "riscv32", target_arch = "riscv64", target_arch = "sparc", From cfe9011d842c77b16515d606a75f4246dd45d60f Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 13 Dec 2023 10:33:32 +0900 Subject: [PATCH 10/25] Update actions/checkout action to v4 --- .github/workflows/ci.yml | 22 +++++++++++----------- .github/workflows/release.yml | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91e729c5e..b9d7d2ec3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: target: armv5te-unknown-linux-gnueabi runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust # --no-self-update is necessary because the windows environment cannot self-update rustup.exe. run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} @@ -79,7 +79,7 @@ jobs: - nightly runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} - name: Install cargo-hack @@ -91,7 +91,7 @@ jobs: dependencies: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update nightly && rustup default nightly - name: Install cargo-hack @@ -108,7 +108,7 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update nightly && rustup default nightly - run: ci/no_atomic.sh @@ -141,7 +141,7 @@ jobs: rustfmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update stable - name: rustfmt @@ -153,7 +153,7 @@ jobs: # clippy: # runs-on: ubuntu-latest # steps: - # - uses: actions/checkout@v3 + # - uses: actions/checkout@v4 # - name: Install Rust # run: rustup update stable # - name: clippy @@ -163,7 +163,7 @@ jobs: miri: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup toolchain install nightly --component miri && rustup default nightly - name: miri @@ -173,7 +173,7 @@ jobs: san: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update nightly && rustup default nightly - name: Run sanitizers @@ -183,7 +183,7 @@ jobs: loom: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update stable - name: loom @@ -193,7 +193,7 @@ jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update nightly && rustup default nightly - name: docs @@ -202,7 +202,7 @@ jobs: shellcheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install shellcheck uses: taiki-e/install-action@shellcheck - run: shellcheck $(git ls-files '*.sh') diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad0813010..514f11b5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: if: github.repository_owner == 'crossbeam-rs' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: taiki-e/create-gh-release-action@v1 with: prefix: crossbeam(-[a-z]+)? From 8bdd4eaf304bfdacffd2467ca9de20b7fcbc6a5a Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 10 Sep 2023 15:31:13 +0900 Subject: [PATCH 11/25] CachePadded: Use 64-byte alignment on riscv32 and riscv64 --- crossbeam-utils/src/cache_padded.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crossbeam-utils/src/cache_padded.rs b/crossbeam-utils/src/cache_padded.rs index 4978a3eb3..f44f2d7b4 100644 --- a/crossbeam-utils/src/cache_padded.rs +++ b/crossbeam-utils/src/cache_padded.rs @@ -14,7 +14,7 @@ use core::ops::{Deref, DerefMut}; /// Cache lines are assumed to be N bytes long, depending on the architecture: /// /// * On x86-64, aarch64, and powerpc64, N = 128. -/// * On arm, mips, mips64, riscv32, riscv64, sparc, and hexagon, N = 32. +/// * On arm, mips, mips64, sparc, and hexagon, N = 32. /// * On m68k, N = 16. /// * On s390x, N = 256. /// * On all others, N = 64. @@ -76,6 +76,7 @@ use core::ops::{Deref, DerefMut}; // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/powerpc/include/asm/cache.h#L26 #[cfg_attr( any( target_arch = "x86_64", @@ -84,18 +85,15 @@ use core::ops::{Deref, DerefMut}; ), repr(align(128)) )] -// arm, mips, mips64, riscv64, sparc, and hexagon have 32-byte cache line size. +// arm, mips, mips64, sparc, and hexagon have 32-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 -// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L17 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/hexagon/include/asm/cache.h#L12 -// -// riscv32 is assumed not to exceed the cache line size of riscv64. #[cfg_attr( any( target_arch = "arm", @@ -103,8 +101,6 @@ use core::ops::{Deref, DerefMut}; target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", - target_arch = "riscv32", - target_arch = "riscv64", target_arch = "sparc", target_arch = "hexagon", ), @@ -121,11 +117,12 @@ use core::ops::{Deref, DerefMut}; // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/s390/include/asm/cache.h#L13 #[cfg_attr(target_arch = "s390x", repr(align(256)))] -// x86, wasm, and sparc64 have 64-byte cache line size. +// x86, wasm, riscv, and sparc64 have 64-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/riscv/include/asm/cache.h#L10 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L19 // // All others are assumed to have 64-byte cache line size. @@ -139,8 +136,6 @@ use core::ops::{Deref, DerefMut}; target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", - target_arch = "riscv32", - target_arch = "riscv64", target_arch = "sparc", target_arch = "hexagon", target_arch = "m68k", From 006cffc56b5dc3e75949cb6808c68b80af882387 Mon Sep 17 00:00:00 2001 From: Lin Yang Date: Tue, 12 Sep 2023 04:08:22 -0700 Subject: [PATCH 12/25] epoch: Fix false sharing in Local struct (#1026) The perf c2c data shows lots of cacheline contention were caused by false sharing between epoch and other field in "Local" struct. So use CachePadded class to align it to another cacheline to resolve this issue. --- crossbeam-epoch/src/internal.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index 00c66a40a..974230a26 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -273,9 +273,6 @@ pub(crate) struct Local { /// A node in the intrusive linked list of `Local`s. entry: Entry, - /// The local epoch. - epoch: AtomicEpoch, - /// A reference to the global data. /// /// When all guards and handles get dropped, this reference is destroyed. @@ -294,6 +291,9 @@ pub(crate) struct Local { /// /// This is just an auxiliary counter that sometimes kicks off collection. pin_count: Cell>, + + /// The local epoch. + epoch: CachePadded, } // Make sure `Local` is less than or equal to 2048 bytes. @@ -320,12 +320,12 @@ impl Local { let local = Owned::new(Local { entry: Entry::default(), - epoch: AtomicEpoch::new(Epoch::starting()), collector: UnsafeCell::new(ManuallyDrop::new(collector.clone())), bag: UnsafeCell::new(Bag::new()), guard_count: Cell::new(0), handle_count: Cell::new(1), pin_count: Cell::new(Wrapping(0)), + epoch: CachePadded::new(AtomicEpoch::new(Epoch::starting())), }) .into_shared(unprotected()); collector.global.locals.insert(local, unprotected()); From c45570e87c602e4c55907897971dd650a0ef7ee4 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 2 Oct 2023 22:25:24 +0900 Subject: [PATCH 13/25] Update loom to 0.7.1 --- crossbeam-epoch/Cargo.toml | 2 +- crossbeam-epoch/src/atomic.rs | 16 +--------------- crossbeam-utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 651f3698a..04af4d667 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -55,7 +55,7 @@ scopeguard = { version = "1.1", default-features = false } # 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.7", optional = true } +loom-crate = { package = "loom", version = "0.7.1", optional = true } [dependencies.crossbeam-utils] version = "0.8.5" diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 0eb041494..473caed09 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -879,17 +879,7 @@ impl Atomic { /// } /// ``` pub unsafe fn into_owned(self) -> Owned { - #[cfg(crossbeam_loom)] - { - // FIXME: loom does not yet support into_inner, so we use unsync_load for now, - // which should have the same synchronization properties: - // https://github.com/tokio-rs/loom/issues/117 - Owned::from_usize(self.data.unsync_load()) - } - #[cfg(not(crossbeam_loom))] - { - Owned::from_usize(self.data.into_inner()) - } + Owned::from_usize(self.data.into_inner()) } /// Takes ownership of the pointee if it is non-null. @@ -926,10 +916,6 @@ impl Atomic { /// } /// ``` pub unsafe fn try_into_owned(self) -> Option> { - // FIXME: See self.into_owned() - #[cfg(crossbeam_loom)] - let data = self.data.unsync_load(); - #[cfg(not(crossbeam_loom))] let data = self.data.into_inner(); if decompose_tag::(data).0 == 0 { None diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 2258552f8..c175f45f0 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -38,7 +38,7 @@ cfg-if = "1" # 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.7", optional = true } +loom = { version = "0.7.1", optional = true } [dev-dependencies] rand = "0.8" From dddb62f943e546615a61ef0e1989c7c3a72bc788 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 Nov 2023 20:58:41 +0900 Subject: [PATCH 14/25] Bump MSRV to Rust 1.61 --- .github/workflows/ci.yml | 6 +++--- Cargo.toml | 2 +- README.md | 4 ++-- crossbeam-channel/Cargo.toml | 2 +- crossbeam-channel/README.md | 4 ++-- crossbeam-deque/Cargo.toml | 2 +- crossbeam-deque/README.md | 4 ++-- crossbeam-epoch/Cargo.toml | 2 +- crossbeam-epoch/README.md | 4 ++-- crossbeam-queue/Cargo.toml | 2 +- crossbeam-queue/README.md | 4 ++-- crossbeam-skiplist/Cargo.toml | 2 +- crossbeam-skiplist/README.md | 4 ++-- crossbeam-utils/Cargo.toml | 2 +- crossbeam-utils/README.md | 4 ++-- crossbeam-utils/src/atomic/atomic_cell.rs | 2 +- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9d7d2ec3..9a626d91d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,9 +30,9 @@ jobs: fail-fast: false matrix: include: - - rust: '1.38' + - rust: '1.61' os: ubuntu-latest - - rust: '1.38' + - rust: '1.61' os: windows-latest - rust: stable os: ubuntu-latest @@ -75,7 +75,7 @@ jobs: fail-fast: false matrix: rust: - - '1.38' + - '1.61' - nightly runs-on: ubuntu-latest steps: diff --git a/Cargo.toml b/Cargo.toml index 6b6882a8c..b89cb5d7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam" # - Create "crossbeam-X.Y.Z" git tag version = "0.8.2" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam" diff --git a/README.md b/README.md index 1e1d68662..de4fcf631 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam#license) https://crates.io/crates/crossbeam) [![Documentation](https://docs.rs/crossbeam/badge.svg)]( https://docs.rs/crossbeam) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -94,7 +94,7 @@ crossbeam = "0.8" Crossbeam supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## Contributing diff --git a/crossbeam-channel/Cargo.toml b/crossbeam-channel/Cargo.toml index a15528029..a39e0d767 100644 --- a/crossbeam-channel/Cargo.toml +++ b/crossbeam-channel/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-channel" # - Create "crossbeam-channel-X.Y.Z" git tag version = "0.5.8" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel" diff --git a/crossbeam-channel/README.md b/crossbeam-channel/README.md index 4c42d863c..90ed205e3 100644 --- a/crossbeam-channel/README.md +++ b/crossbeam-channel/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel#license) https://crates.io/crates/crossbeam-channel) [![Documentation](https://docs.rs/crossbeam-channel/badge.svg)]( https://docs.rs/crossbeam-channel) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -48,7 +48,7 @@ crossbeam-channel = "0.5" Crossbeam Channel supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-deque/Cargo.toml b/crossbeam-deque/Cargo.toml index 805a7e005..c25889c9e 100644 --- a/crossbeam-deque/Cargo.toml +++ b/crossbeam-deque/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-deque" # - Create "crossbeam-deque-X.Y.Z" git tag version = "0.8.3" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque" diff --git a/crossbeam-deque/README.md b/crossbeam-deque/README.md index 23c8794c2..4eae1447e 100644 --- a/crossbeam-deque/README.md +++ b/crossbeam-deque/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque#license) https://crates.io/crates/crossbeam-deque) [![Documentation](https://docs.rs/crossbeam-deque/badge.svg)]( https://docs.rs/crossbeam-deque) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -28,7 +28,7 @@ crossbeam-deque = "0.8" Crossbeam Deque supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 04af4d667..077621cc4 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-epoch" # - Create "crossbeam-epoch-X.Y.Z" git tag version = "0.9.15" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch" diff --git a/crossbeam-epoch/README.md b/crossbeam-epoch/README.md index 2840ea792..ba74c7c75 100644 --- a/crossbeam-epoch/README.md +++ b/crossbeam-epoch/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch#license) https://crates.io/crates/crossbeam-epoch) [![Documentation](https://docs.rs/crossbeam-epoch/badge.svg)]( https://docs.rs/crossbeam-epoch) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -35,7 +35,7 @@ crossbeam-epoch = "0.9" Crossbeam Epoch supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-queue/Cargo.toml b/crossbeam-queue/Cargo.toml index 27c386c51..0d96de380 100644 --- a/crossbeam-queue/Cargo.toml +++ b/crossbeam-queue/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-queue" # - Create "crossbeam-queue-X.Y.Z" git tag version = "0.3.8" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-queue" diff --git a/crossbeam-queue/README.md b/crossbeam-queue/README.md index 85671ef17..6b3372ce6 100644 --- a/crossbeam-queue/README.md +++ b/crossbeam-queue/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-queue#license) https://crates.io/crates/crossbeam-queue) [![Documentation](https://docs.rs/crossbeam-queue/badge.svg)]( https://docs.rs/crossbeam-queue) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -36,7 +36,7 @@ crossbeam-queue = "0.3" Crossbeam Queue supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-skiplist/Cargo.toml b/crossbeam-skiplist/Cargo.toml index 9f3f17c68..2a179a5c2 100644 --- a/crossbeam-skiplist/Cargo.toml +++ b/crossbeam-skiplist/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-skiplist" # - Create "crossbeam-skiplist-X.Y.Z" git tag version = "0.0.0" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-skiplist" diff --git a/crossbeam-skiplist/README.md b/crossbeam-skiplist/README.md index 4c9509061..2de167859 100644 --- a/crossbeam-skiplist/README.md +++ b/crossbeam-skiplist/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-skiplist#license https://crates.io/crates/crossbeam-skiplist) [![Documentation](https://docs.rs/crossbeam-skiplist/badge.svg)]( https://docs.rs/crossbeam-skiplist) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -31,7 +31,7 @@ crossbeam-skiplist = "0.1" Crossbeam Skiplist supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index c175f45f0..5bc1a1996 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -6,7 +6,7 @@ name = "crossbeam-utils" # - Create "crossbeam-utils-X.Y.Z" git tag version = "0.8.16" edition = "2018" -rust-version = "1.38" +rust-version = "1.61" license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils" diff --git a/crossbeam-utils/README.md b/crossbeam-utils/README.md index c06ea601a..7f87fcb1d 100644 --- a/crossbeam-utils/README.md +++ b/crossbeam-utils/README.md @@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils#license) https://crates.io/crates/crossbeam-utils) [![Documentation](https://docs.rs/crossbeam-utils/badge.svg)]( https://docs.rs/crossbeam-utils) -[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)]( +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) @@ -55,7 +55,7 @@ crossbeam-utils = "0.8" Crossbeam Utils supports stable Rust releases going back at least six months, and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.38. +version is released. Currently, the minimum supported Rust version is 1.61. ## License diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 7941c5c87..ff79bcd70 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -968,7 +968,7 @@ 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 our MSRV (Rust 1.38). + // HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in our MSRV (Rust 1.61). let is_lock_free = can_transmute::() | can_transmute::() | can_transmute::() From 00fddfd53967cb0120ff4c87e05ab12ba786709a Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 Nov 2023 21:25:11 +0900 Subject: [PATCH 15/25] Remove build scripts from most crates and clean up no_atomic handling --- ci/no_atomic.sh | 38 +++---------- crossbeam-epoch/Cargo.toml | 1 - crossbeam-epoch/build-common.rs | 1 - crossbeam-epoch/build.rs | 57 ------------------- crossbeam-epoch/no_atomic.rs | 1 - crossbeam-epoch/src/atomic.rs | 11 ---- crossbeam-epoch/src/lib.rs | 4 +- crossbeam-queue/build-common.rs | 1 - crossbeam-queue/build.rs | 41 -------------- crossbeam-queue/no_atomic.rs | 1 - crossbeam-queue/src/lib.rs | 2 +- crossbeam-skiplist/build-common.rs | 1 - crossbeam-skiplist/build.rs | 41 -------------- crossbeam-skiplist/no_atomic.rs | 1 - crossbeam-skiplist/src/lib.rs | 2 +- crossbeam-utils/Cargo.toml | 1 - crossbeam-utils/build.rs | 20 ------- crossbeam-utils/src/atomic/atomic_cell.rs | 12 ++-- crossbeam-utils/src/atomic/consume.rs | 12 +++- crossbeam-utils/src/atomic/mod.rs | 6 +- crossbeam-utils/src/lib.rs | 12 +++- crossbeam-utils/tests/atomic_cell.rs | 8 +-- no_atomic.rs | 68 ----------------------- 23 files changed, 43 insertions(+), 299 deletions(-) delete mode 120000 crossbeam-epoch/build-common.rs delete mode 100644 crossbeam-epoch/build.rs delete mode 120000 crossbeam-epoch/no_atomic.rs delete mode 120000 crossbeam-queue/build-common.rs delete mode 100644 crossbeam-queue/build.rs delete mode 120000 crossbeam-queue/no_atomic.rs delete mode 120000 crossbeam-skiplist/build-common.rs delete mode 100644 crossbeam-skiplist/build.rs delete mode 120000 crossbeam-skiplist/no_atomic.rs diff --git a/ci/no_atomic.sh b/ci/no_atomic.sh index 186b8bcce..44bd008ba 100755 --- a/ci/no_atomic.sh +++ b/ci/no_atomic.sh @@ -10,30 +10,26 @@ cd "$(dirname "$0")"/.. file="no_atomic.rs" -no_atomic_cas=() -no_atomic_64=() no_atomic=() -for target in $(rustc --print target-list); do - target_spec=$(rustc --print target-spec-json -Z unstable-options --target "${target}") +for target_spec in $(rustc -Z unstable-options --print all-target-specs-json | jq -c '. | to_entries | .[]'); do + target=$(jq <<<"${target_spec}" -r '.key') + target_spec=$(jq <<<"${target_spec}" -c '.value') res=$(jq <<<"${target_spec}" -r 'select(."atomic-cas" == false)') [[ -z "${res}" ]] || no_atomic_cas+=("${target}") max_atomic_width=$(jq <<<"${target_spec}" -r '."max-atomic-width"') min_atomic_width=$(jq <<<"${target_spec}" -r '."min-atomic-width"') case "${max_atomic_width}" in + # `"max-atomic-width" == 0` means that atomic is not supported at all. + # We do not have a cfg for targets with {8,16}-bit atomic only, so + # for now we treat them the same as targets that do not support atomic. + 0) no_atomic+=("${target}") ;; # 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. - 32 | null) no_atomic_64+=("${target}") ;; - # `"max-atomic-width" == 0` means that atomic is not supported at all. - 0) - no_atomic_64+=("${target}") - no_atomic+=("${target}") - ;; - 64 | 128) ;; - # There is no `"max-atomic-width" == 16` or `"max-atomic-width" == 8` targets. + null | 8 | 16 | 32 | 64 | 128) ;; *) exit 1 ;; esac case "${min_atomic_width}" in @@ -46,24 +42,6 @@ cat >"${file}" <>"${file}" -done -cat >>"${file}" <>"${file}" -done -cat >>"${file}" < convert_custom_linux_target(target), - Err(e) => { - println!( - "cargo:warning={}: unable to get TARGET environment variable: {}", - env!("CARGO_PKG_NAME"), - e - ); - return; - } - }; - - let cfg = match autocfg::AutoCfg::new() { - Ok(cfg) => cfg, - Err(e) => { - println!( - "cargo:warning={}: unable to determine rustc version: {}", - env!("CARGO_PKG_NAME"), - e - ); - return; - } - }; - - // Note that this is `no_`*, not `has_*`. This allows treating as the latest - // stable rustc is used when the build script doesn't run. This is useful - // for 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"); - } - - if !cfg.probe_rustc_version(1, 61) { - println!("cargo:rustc-cfg=crossbeam_no_const_fn_trait_bound"); - } -} diff --git a/crossbeam-epoch/no_atomic.rs b/crossbeam-epoch/no_atomic.rs deleted file mode 120000 index 417886bb7..000000000 --- a/crossbeam-epoch/no_atomic.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 473caed09..4dcabcdd3 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -344,7 +344,6 @@ impl Atomic { /// /// let a = Atomic::::null(); /// ``` - #[cfg(all(not(crossbeam_no_const_fn_trait_bound), not(crossbeam_loom)))] pub const fn null() -> Atomic { Self { data: AtomicUsize::new(0), @@ -352,15 +351,6 @@ impl Atomic { } } - /// Returns a new null atomic pointer. - #[cfg(not(all(not(crossbeam_no_const_fn_trait_bound), not(crossbeam_loom))))] - pub fn null() -> Atomic { - Self { - data: AtomicUsize::new(0), - _marker: PhantomData, - } - } - /// Loads a `Shared` from the atomic pointer. /// /// This method takes an [`Ordering`] argument which describes the memory ordering of this @@ -1685,7 +1675,6 @@ mod tests { Shared::::null().with_tag(7); } - #[rustversion::since(1.61)] #[test] fn const_atomic_null() { use super::Atomic; diff --git a/crossbeam-epoch/src/lib.rs b/crossbeam-epoch/src/lib.rs index 94d5db1bc..0310ba453 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -89,7 +89,7 @@ mod primitive { } pub(crate) use loom::thread_local; } -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] #[cfg(not(crossbeam_loom))] #[allow(unused_imports, dead_code)] mod primitive { @@ -132,7 +132,7 @@ mod primitive { pub(crate) use std::thread_local; } -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-queue/build-common.rs b/crossbeam-queue/build-common.rs deleted file mode 120000 index 929510c73..000000000 --- a/crossbeam-queue/build-common.rs +++ /dev/null @@ -1 +0,0 @@ -../build-common.rs \ No newline at end of file diff --git a/crossbeam-queue/build.rs b/crossbeam-queue/build.rs deleted file mode 100644 index ffa02a663..000000000 --- a/crossbeam-queue/build.rs +++ /dev/null @@ -1,41 +0,0 @@ -// The rustc-cfg listed below are considered public API, but it is *unstable* -// and outside of the normal semver guarantees: -// -// - `crossbeam_no_atomic_cas` -// Assume the target does *not* support atomic CAS operations. -// This is usually detected automatically by the build script, but you may -// need to enable it manually when building for custom targets or using -// non-cargo build systems that don't run the build script. -// -// With the exceptions mentioned above, the rustc-cfg emitted by the build -// script are *not* public API. - -#![warn(rust_2018_idioms)] - -use std::env; - -include!("no_atomic.rs"); -include!("build-common.rs"); - -fn main() { - println!("cargo:rerun-if-changed=no_atomic.rs"); - - let target = match env::var("TARGET") { - Ok(target) => convert_custom_linux_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 as the latest - // stable rustc is used when the build script doesn't run. This is useful - // for 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"); - } -} diff --git a/crossbeam-queue/no_atomic.rs b/crossbeam-queue/no_atomic.rs deleted file mode 120000 index 417886bb7..000000000 --- a/crossbeam-queue/no_atomic.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-queue/src/lib.rs b/crossbeam-queue/src/lib.rs index 846d7c2e1..36687282a 100644 --- a/crossbeam-queue/src/lib.rs +++ b/crossbeam-queue/src/lib.rs @@ -20,7 +20,7 @@ )] #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] cfg_if::cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-skiplist/build-common.rs b/crossbeam-skiplist/build-common.rs deleted file mode 120000 index 929510c73..000000000 --- a/crossbeam-skiplist/build-common.rs +++ /dev/null @@ -1 +0,0 @@ -../build-common.rs \ No newline at end of file diff --git a/crossbeam-skiplist/build.rs b/crossbeam-skiplist/build.rs deleted file mode 100644 index ffa02a663..000000000 --- a/crossbeam-skiplist/build.rs +++ /dev/null @@ -1,41 +0,0 @@ -// The rustc-cfg listed below are considered public API, but it is *unstable* -// and outside of the normal semver guarantees: -// -// - `crossbeam_no_atomic_cas` -// Assume the target does *not* support atomic CAS operations. -// This is usually detected automatically by the build script, but you may -// need to enable it manually when building for custom targets or using -// non-cargo build systems that don't run the build script. -// -// With the exceptions mentioned above, the rustc-cfg emitted by the build -// script are *not* public API. - -#![warn(rust_2018_idioms)] - -use std::env; - -include!("no_atomic.rs"); -include!("build-common.rs"); - -fn main() { - println!("cargo:rerun-if-changed=no_atomic.rs"); - - let target = match env::var("TARGET") { - Ok(target) => convert_custom_linux_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 as the latest - // stable rustc is used when the build script doesn't run. This is useful - // for 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"); - } -} diff --git a/crossbeam-skiplist/no_atomic.rs b/crossbeam-skiplist/no_atomic.rs deleted file mode 120000 index 417886bb7..000000000 --- a/crossbeam-skiplist/no_atomic.rs +++ /dev/null @@ -1 +0,0 @@ -../no_atomic.rs \ No newline at end of file diff --git a/crossbeam-skiplist/src/lib.rs b/crossbeam-skiplist/src/lib.rs index cb5f0462d..194823800 100644 --- a/crossbeam-skiplist/src/lib.rs +++ b/crossbeam-skiplist/src/lib.rs @@ -245,7 +245,7 @@ use cfg_if::cfg_if; -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] cfg_if! { if #[cfg(feature = "alloc")] { extern crate alloc; diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 5bc1a1996..294ac97c5 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -42,4 +42,3 @@ loom = { version = "0.7.1", optional = true } [dev-dependencies] rand = "0.8" -rustversion = "1" diff --git a/crossbeam-utils/build.rs b/crossbeam-utils/build.rs index 39785f030..c71c23136 100644 --- a/crossbeam-utils/build.rs +++ b/crossbeam-utils/build.rs @@ -1,24 +1,12 @@ // The rustc-cfg listed below are considered public API, but it is *unstable* // and outside of the normal semver guarantees: // -// - `crossbeam_no_atomic_cas` -// Assume the target does *not* support atomic CAS operations. -// This is usually detected automatically by the build script, but you may -// need to enable it manually when building for custom targets or using -// non-cargo build systems that don't run the build script. -// // - `crossbeam_no_atomic` // Assume the target does *not* support any atomic operations. // This is usually detected automatically by the build script, but you may // need to enable it manually when building for custom targets or using // non-cargo build systems that don't run the build script. // -// - `crossbeam_no_atomic_64` -// Assume the target does *not* support AtomicU64/AtomicI64. -// This is usually detected automatically by the build script, but you may -// need to enable it manually when building for custom targets or using -// non-cargo build systems that don't run the build script. -// // With the exceptions mentioned above, the rustc-cfg emitted by the build // script are *not* public API. @@ -47,16 +35,8 @@ fn main() { // Note that this is `no_`*, not `has_*`. This allows treating as the latest // stable rustc is used when the build script doesn't run. This is useful // for 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"); - } 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` or `"max-atomic-width" == 128`. } // `cfg(sanitize = "..")` is not stabilized. diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index ff79bcd70..ee679f5b7 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -725,13 +725,13 @@ impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);"); impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);"); impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);"); impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);"); -#[cfg(not(crossbeam_no_atomic_64))] +#[cfg(target_has_atomic = "64")] impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);"); -#[cfg(not(crossbeam_no_atomic_64))] +#[cfg(target_has_atomic = "64")] impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);"); -#[cfg(crossbeam_no_atomic_64)] +#[cfg(not(target_has_atomic = "64"))] impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);"); -#[cfg(crossbeam_no_atomic_64)] +#[cfg(not(target_has_atomic = "64"))] impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);"); // TODO: AtomicU128 is unstable // impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);"); @@ -956,7 +956,7 @@ macro_rules! atomic { atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); - #[cfg(not(crossbeam_no_atomic_64))] + #[cfg(target_has_atomic = "64")] atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); // TODO: AtomicU128 is unstable // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); @@ -973,7 +973,7 @@ const fn atomic_is_lock_free() -> bool { | can_transmute::() | can_transmute::() | can_transmute::(); - #[cfg(not(crossbeam_no_atomic_64))] + #[cfg(target_has_atomic = "64")] let is_lock_free = is_lock_free | can_transmute::(); // TODO: AtomicU128 is unstable // let is_lock_free = is_lock_free | can_transmute::(); diff --git a/crossbeam-utils/src/atomic/consume.rs b/crossbeam-utils/src/atomic/consume.rs index 80a88829b..ff8e316b2 100644 --- a/crossbeam-utils/src/atomic/consume.rs +++ b/crossbeam-utils/src/atomic/consume.rs @@ -83,11 +83,19 @@ impl_atomic!(AtomicU8, u8); impl_atomic!(AtomicI8, i8); impl_atomic!(AtomicU16, u16); impl_atomic!(AtomicI16, i16); +#[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] impl_atomic!(AtomicU32, u32); +#[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] impl_atomic!(AtomicI32, i32); -#[cfg(not(crossbeam_no_atomic_64))] +#[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), +))] impl_atomic!(AtomicU64, u64); -#[cfg(not(crossbeam_no_atomic_64))] +#[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), +))] impl_atomic!(AtomicI64, i64); #[cfg(not(crossbeam_no_atomic))] diff --git a/crossbeam-utils/src/atomic/mod.rs b/crossbeam-utils/src/atomic/mod.rs index 38967859f..4332cc3bd 100644 --- a/crossbeam-utils/src/atomic/mod.rs +++ b/crossbeam-utils/src/atomic/mod.rs @@ -3,7 +3,7 @@ //! * [`AtomicCell`], a thread-safe mutable memory location. //! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering. -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] #[cfg(not(crossbeam_loom))] cfg_if::cfg_if! { // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap @@ -23,7 +23,7 @@ cfg_if::cfg_if! { } } -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] // We cannot provide AtomicCell under cfg(crossbeam_loom) because loom's atomic // types have a different in-memory representation than the underlying type. // TODO: The latest loom supports fences, so fallback using seqlock may be available. @@ -31,7 +31,7 @@ cfg_if::cfg_if! { mod atomic_cell; mod consume; -#[cfg(not(crossbeam_no_atomic_cas))] +#[cfg(target_has_atomic = "ptr")] #[cfg(not(crossbeam_loom))] 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 191c5a17d..7384d1155 100644 --- a/crossbeam-utils/src/lib.rs +++ b/crossbeam-utils/src/lib.rs @@ -72,10 +72,16 @@ mod primitive { pub(crate) use core::sync::atomic::spin_loop_hint; #[cfg(not(crossbeam_no_atomic))] pub(crate) use core::sync::atomic::{ - AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, - AtomicU8, AtomicUsize, + AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicU16, AtomicU8, AtomicUsize, }; - #[cfg(not(crossbeam_no_atomic_64))] + #[cfg(not(crossbeam_no_atomic))] + #[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] + pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32}; + #[cfg(not(crossbeam_no_atomic))] + #[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), + ))] pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64}; } diff --git a/crossbeam-utils/tests/atomic_cell.rs b/crossbeam-utils/tests/atomic_cell.rs index edb7a4bc0..7a2689d99 100644 --- a/crossbeam-utils/tests/atomic_cell.rs +++ b/crossbeam-utils/tests/atomic_cell.rs @@ -35,13 +35,13 @@ fn is_lock_free() { // of `AtomicU64` is `8`, so `AtomicCell` is not lock-free. assert_eq!( AtomicCell::::is_lock_free(), - cfg!(not(crossbeam_no_atomic_64)) && std::mem::align_of::() == 8 + cfg!(target_has_atomic = "64") && std::mem::align_of::() == 8 ); assert_eq!(mem::size_of::(), 8); assert_eq!(mem::align_of::(), 8); assert_eq!( AtomicCell::::is_lock_free(), - cfg!(not(crossbeam_no_atomic_64)) + cfg!(target_has_atomic = "64") ); // AtomicU128 is unstable @@ -307,7 +307,6 @@ test_arithmetic!(arithmetic_i128, i128); // https://github.com/crossbeam-rs/crossbeam/issues/748 #[cfg_attr(miri, ignore)] // TODO -#[rustversion::since(1.37)] // #[repr(align(N))] requires Rust 1.37 #[test] fn issue_748() { #[allow(dead_code)] @@ -321,14 +320,13 @@ fn issue_748() { assert_eq!(mem::size_of::(), 8); assert_eq!( AtomicCell::::is_lock_free(), - cfg!(not(crossbeam_no_atomic_64)) + cfg!(target_has_atomic = "64") ); let x = AtomicCell::new(Test::FieldLess); assert_eq!(x.load(), Test::FieldLess); } // https://github.com/crossbeam-rs/crossbeam/issues/833 -#[rustversion::since(1.40)] // const_constructor requires Rust 1.40 #[test] fn issue_833() { use std::num::NonZeroU128; diff --git a/no_atomic.rs b/no_atomic.rs index 3e19722fc..b97f39706 100644 --- a/no_atomic.rs +++ b/no_atomic.rs @@ -1,75 +1,7 @@ // This file is @generated by no_atomic.sh. // It is not intended for manual editing. -const NO_ATOMIC_CAS: &[&str] = &[ - "armv4t-none-eabi", - "armv5te-none-eabi", - "avr-unknown-gnu-atmega328", - "bpfeb-unknown-none", - "bpfel-unknown-none", - "msp430-none-elf", - "riscv32i-unknown-none-elf", - "riscv32im-unknown-none-elf", - "riscv32imc-unknown-none-elf", - "thumbv4t-none-eabi", - "thumbv5te-none-eabi", - "thumbv6m-none-eabi", -]; - -#[allow(dead_code)] // Only crossbeam-utils uses this. -const NO_ATOMIC_64: &[&str] = &[ - "arm-linux-androideabi", - "armv4t-none-eabi", - "armv4t-unknown-linux-gnueabi", - "armv5te-none-eabi", - "armv5te-unknown-linux-gnueabi", - "armv5te-unknown-linux-musleabi", - "armv5te-unknown-linux-uclibceabi", - "armv6k-nintendo-3ds", - "avr-unknown-gnu-atmega328", - "hexagon-unknown-linux-musl", - "m68k-unknown-linux-gnu", - "mips-unknown-linux-gnu", - "mips-unknown-linux-musl", - "mips-unknown-linux-uclibc", - "mipsel-sony-psp", - "mipsel-sony-psx", - "mipsel-unknown-linux-gnu", - "mipsel-unknown-linux-musl", - "mipsel-unknown-linux-uclibc", - "mipsel-unknown-none", - "mipsisa32r6-unknown-linux-gnu", - "mipsisa32r6el-unknown-linux-gnu", - "msp430-none-elf", - "powerpc-unknown-freebsd", - "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", - "riscv32i-unknown-none-elf", - "riscv32im-unknown-none-elf", - "riscv32imac-unknown-none-elf", - "riscv32imac-unknown-xous-elf", - "riscv32imc-unknown-none-elf", - "thumbv4t-none-eabi", - "thumbv5te-none-eabi", - "thumbv6m-none-eabi", - "thumbv7em-none-eabi", - "thumbv7em-none-eabihf", - "thumbv7m-none-eabi", - "thumbv8m.base-none-eabi", - "thumbv8m.main-none-eabi", - "thumbv8m.main-none-eabihf", -]; - -#[allow(dead_code)] // Only crossbeam-utils uses this. const NO_ATOMIC: &[&str] = &[ - "avr-unknown-gnu-atmega328", "bpfeb-unknown-none", "bpfel-unknown-none", "mipsel-sony-psx", From 5096ddffc1a3d7ef2cbf7ee9c04d98a058556d7c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 Nov 2023 21:42:06 +0900 Subject: [PATCH 16/25] Resolve some MSRV-related TODOs --- crossbeam-epoch/src/atomic.rs | 3 +-- crossbeam-epoch/src/epoch.rs | 3 +-- crossbeam-epoch/src/internal.rs | 3 +-- crossbeam-epoch/src/lib.rs | 6 ++++-- crossbeam-utils/src/atomic/atomic_cell.rs | 14 ++------------ crossbeam-utils/src/backoff.rs | 17 ++++------------- crossbeam-utils/src/lib.rs | 15 ++++++++------- crossbeam-utils/src/sync/once_lock.rs | 19 +++---------------- crossbeam-utils/src/sync/parker.rs | 3 +-- 9 files changed, 25 insertions(+), 58 deletions(-) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 4dcabcdd3..f6e52ac8c 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -5,12 +5,11 @@ use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::slice; -use core::sync::atomic::Ordering; use crate::alloc::alloc; use crate::alloc::boxed::Box; use crate::guard::Guard; -use crate::primitive::sync::atomic::AtomicUsize; +use crate::primitive::sync::atomic::{AtomicUsize, Ordering}; use crossbeam_utils::atomic::AtomicConsume; /// Given ordering for the success case in a compare-exchange operation, returns the strongest diff --git a/crossbeam-epoch/src/epoch.rs b/crossbeam-epoch/src/epoch.rs index 663508bd7..18d7418a1 100644 --- a/crossbeam-epoch/src/epoch.rs +++ b/crossbeam-epoch/src/epoch.rs @@ -7,8 +7,7 @@ //! If an object became garbage in some epoch, then we can be sure that after two advancements no //! participant will hold a reference to it. That is the crux of safe memory reclamation. -use crate::primitive::sync::atomic::AtomicUsize; -use core::sync::atomic::Ordering; +use crate::primitive::sync::atomic::{AtomicUsize, Ordering}; /// An epoch that can be marked as pinned or unpinned. /// diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index 974230a26..93065fa6b 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -36,11 +36,10 @@ //! destroyed as soon as the data structure gets dropped. use crate::primitive::cell::UnsafeCell; -use crate::primitive::sync::atomic; +use crate::primitive::sync::atomic::{self, Ordering}; use core::cell::Cell; use core::mem::{self, ManuallyDrop}; use core::num::Wrapping; -use core::sync::atomic::Ordering; use core::{fmt, ptr}; use crossbeam_utils::CachePadded; diff --git a/crossbeam-epoch/src/lib.rs b/crossbeam-epoch/src/lib.rs index 0310ba453..96374edde 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -76,7 +76,7 @@ mod primitive { } pub(crate) mod sync { pub(crate) mod atomic { - pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize}; + pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering}; // FIXME: loom does not support compiler_fence at the moment. // https://github.com/tokio-rs/loom/issues/117 @@ -122,7 +122,9 @@ mod primitive { } pub(crate) mod sync { pub(crate) mod atomic { - pub(crate) use core::sync::atomic::{compiler_fence, fence, AtomicPtr, AtomicUsize}; + pub(crate) use core::sync::atomic::{ + compiler_fence, fence, AtomicPtr, AtomicUsize, Ordering, + }; } #[cfg(feature = "alloc")] pub(crate) use alloc::sync::Arc; diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index ee679f5b7..b71ca6f95 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -1,12 +1,11 @@ // Necessary for implementing atomic methods for `AtomicUnit` #![allow(clippy::unit_arg)] -use crate::primitive::sync::atomic::{self, AtomicBool}; +use crate::primitive::sync::atomic::{self, AtomicBool, Ordering}; use core::cell::UnsafeCell; use core::cmp; use core::fmt; use core::mem::{self, ManuallyDrop, MaybeUninit}; -use core::sync::atomic::Ordering; use core::ptr; @@ -968,16 +967,7 @@ 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 our MSRV (Rust 1.61). - let is_lock_free = can_transmute::() - | can_transmute::() - | can_transmute::() - | can_transmute::(); - #[cfg(target_has_atomic = "64")] - 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 + atomic! { T, _a, true, false } } /// Atomically reads data from `src`. diff --git a/crossbeam-utils/src/backoff.rs b/crossbeam-utils/src/backoff.rs index 9e256aaf2..7a505ed61 100644 --- a/crossbeam-utils/src/backoff.rs +++ b/crossbeam-utils/src/backoff.rs @@ -1,4 +1,4 @@ -use crate::primitive::sync::atomic; +use crate::primitive::hint; use core::cell::Cell; use core::fmt; @@ -145,10 +145,7 @@ impl Backoff { #[inline] pub fn spin(&self) { for _ in 0..1 << self.step.get().min(SPIN_LIMIT) { - // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+, - // use [`core::hint::spin_loop`] instead. - #[allow(deprecated)] - atomic::spin_loop_hint(); + hint::spin_loop(); } if self.step.get() <= SPIN_LIMIT { @@ -209,18 +206,12 @@ impl Backoff { pub fn snooze(&self) { if self.step.get() <= SPIN_LIMIT { for _ in 0..1 << self.step.get() { - // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+, - // use [`core::hint::spin_loop`] instead. - #[allow(deprecated)] - atomic::spin_loop_hint(); + hint::spin_loop(); } } else { #[cfg(not(feature = "std"))] for _ in 0..1 << self.step.get() { - // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+, - // use [`core::hint::spin_loop`] instead. - #[allow(deprecated)] - atomic::spin_loop_hint(); + hint::spin_loop(); } #[cfg(feature = "std")] diff --git a/crossbeam-utils/src/lib.rs b/crossbeam-utils/src/lib.rs index 7384d1155..6ab748f34 100644 --- a/crossbeam-utils/src/lib.rs +++ b/crossbeam-utils/src/lib.rs @@ -42,12 +42,14 @@ #[cfg(crossbeam_loom)] #[allow(unused_imports)] mod primitive { + pub(crate) mod hint { + pub(crate) use loom::hint::spin_loop; + } pub(crate) mod sync { pub(crate) mod atomic { - pub(crate) use loom::sync::atomic::spin_loop_hint; pub(crate) use loom::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, - AtomicU32, AtomicU64, AtomicU8, AtomicUsize, + AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering, }; // FIXME: loom does not support compiler_fence at the moment. @@ -63,13 +65,12 @@ mod primitive { #[cfg(not(crossbeam_loom))] #[allow(unused_imports)] mod primitive { + pub(crate) mod hint { + pub(crate) use core::hint::spin_loop; + } pub(crate) mod sync { pub(crate) mod atomic { - pub(crate) use core::sync::atomic::compiler_fence; - // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+, - // use [`core::hint::spin_loop`] instead. - #[allow(deprecated)] - pub(crate) use core::sync::atomic::spin_loop_hint; + pub(crate) use core::sync::atomic::{compiler_fence, Ordering}; #[cfg(not(crossbeam_no_atomic))] pub(crate) use core::sync::atomic::{ AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicU16, AtomicU8, AtomicUsize, diff --git a/crossbeam-utils/src/sync/once_lock.rs b/crossbeam-utils/src/sync/once_lock.rs index c1fefc96c..761851b01 100644 --- a/crossbeam-utils/src/sync/once_lock.rs +++ b/crossbeam-utils/src/sync/once_lock.rs @@ -4,13 +4,10 @@ use core::cell::UnsafeCell; use core::mem::MaybeUninit; -use core::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; pub(crate) struct OnceLock { once: Once, - // Once::is_completed requires Rust 1.43, so use this to track of whether they have been initialized. - is_initialized: AtomicBool, value: UnsafeCell>, // Unlike std::sync::OnceLock, we don't need PhantomData here because // we don't use #[may_dangle]. @@ -25,7 +22,6 @@ impl OnceLock { pub(crate) const fn new() -> Self { Self { once: Once::new(), - is_initialized: AtomicBool::new(false), value: UnsafeCell::new(MaybeUninit::uninit()), } } @@ -50,37 +46,28 @@ impl OnceLock { F: FnOnce() -> T, { // Fast path check - if self.is_initialized() { + if self.once.is_completed() { // SAFETY: The inner value has been initialized return unsafe { self.get_unchecked() }; } self.initialize(f); - debug_assert!(self.is_initialized()); - // SAFETY: The inner value has been initialized unsafe { self.get_unchecked() } } - #[inline] - fn is_initialized(&self) -> bool { - self.is_initialized.load(Ordering::Acquire) - } - #[cold] fn initialize(&self, f: F) where F: FnOnce() -> T, { let slot = self.value.get().cast::(); - let is_initialized = &self.is_initialized; self.once.call_once(|| { let value = f(); unsafe { slot.write(value); } - is_initialized.store(true, Ordering::Release); }); } @@ -88,14 +75,14 @@ impl OnceLock { /// /// The value must be initialized unsafe fn get_unchecked(&self) -> &T { - debug_assert!(self.is_initialized()); + debug_assert!(self.once.is_completed()); &*self.value.get().cast::() } } impl Drop for OnceLock { fn drop(&mut self) { - if self.is_initialized() { + if self.once.is_completed() { // SAFETY: The inner value has been initialized unsafe { self.value.get().cast::().drop_in_place() }; } diff --git a/crossbeam-utils/src/sync/parker.rs b/crossbeam-utils/src/sync/parker.rs index 9cb3a2601..971981d2b 100644 --- a/crossbeam-utils/src/sync/parker.rs +++ b/crossbeam-utils/src/sync/parker.rs @@ -1,6 +1,5 @@ -use crate::primitive::sync::atomic::AtomicUsize; +use crate::primitive::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::primitive::sync::{Arc, Condvar, Mutex}; -use core::sync::atomic::Ordering::SeqCst; use std::fmt; use std::marker::PhantomData; use std::time::{Duration, Instant}; From 5ded632a88f8510071a75f312a3c2f5021def7a9 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 Nov 2023 22:16:04 +0900 Subject: [PATCH 17/25] AtomicCell: use atomic! macro in the impl_arithmetic! --- crossbeam-utils/src/atomic/atomic_cell.rs | 339 +++++++++++++--------- 1 file changed, 207 insertions(+), 132 deletions(-) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index b71ca6f95..7d295b309 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -1,7 +1,7 @@ // Necessary for implementing atomic methods for `AtomicUnit` #![allow(clippy::unit_arg)] -use crate::primitive::sync::atomic::{self, AtomicBool, Ordering}; +use crate::primitive::sync::atomic::{self, Ordering}; use core::cell::UnsafeCell; use core::cmp; use core::fmt; @@ -321,6 +321,36 @@ impl Drop for AtomicCell { } } +macro_rules! atomic { + // If values of type `$t` can be transmuted into values of the primitive atomic type `$atomic`, + // declares variable `$a` of type `$atomic` and executes `$atomic_op`, breaking out of the loop. + (@check, $t:ty, $atomic:ty, $a:ident, $atomic_op:expr) => { + if can_transmute::<$t, $atomic>() { + let $a: &$atomic; + break $atomic_op; + } + }; + + // If values of type `$t` can be transmuted into values of a primitive atomic type, declares + // variable `$a` of that type and executes `$atomic_op`. Otherwise, just executes + // `$fallback_op`. + ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => { + loop { + atomic!(@check, $t, AtomicUnit, $a, $atomic_op); + + atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); + atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); + atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); + #[cfg(target_has_atomic = "64")] + atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); + // TODO: AtomicU128 is unstable + // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); + + break $fallback_op; + } + }; +} + macro_rules! impl_arithmetic { ($t:ty, fallback, $example:tt) => { impl AtomicCell<$t> { @@ -499,7 +529,7 @@ macro_rules! impl_arithmetic { } } }; - ($t:ty, $atomic:ty, $example:tt) => { + ($t:ty, $atomic:ident, $example:tt) => { impl AtomicCell<$t> { /// Increments the current value by `val` and returns the previous value. /// @@ -517,15 +547,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_add(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_add(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value = value.wrapping_add(val); - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_add(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_add(val); + old + } } } @@ -545,15 +579,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_sub(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_sub(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value = value.wrapping_sub(val); - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_sub(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_sub(val); + old + } } } @@ -571,15 +609,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_and(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_and(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value &= val; - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_and(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value &= val; + old + } } } @@ -597,15 +639,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_nand(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_nand(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value = !(old & val); - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_nand(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = !(old & val); + old + } } } @@ -623,15 +669,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_or(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_or(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value |= val; - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_or(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value |= val; + old + } } } @@ -649,15 +699,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_xor(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - let a = unsafe { &*(self.as_ptr() as *const $atomic) }; - a.fetch_xor(val, Ordering::AcqRel) - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value ^= val; - old + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_xor(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value ^= val; + old + } } } @@ -676,15 +730,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_max(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - // TODO: Atomic*::fetch_max requires Rust 1.45. - self.fetch_update(|old| Some(cmp::max(old, val))).unwrap() - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value = cmp::max(old, val); - old + atomic! { + $t, _a, + { + // TODO: Atomic*::fetch_max requires Rust 1.45. + self.fetch_update(|old| Some(cmp::max(old, val))).unwrap() + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::max(old, val); + old + } } } @@ -703,51 +761,50 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_min(&self, val: $t) -> $t { - if can_transmute::<$t, $atomic>() { - // TODO: Atomic*::fetch_min requires Rust 1.45. - self.fetch_update(|old| Some(cmp::min(old, val))).unwrap() - } else { - let _guard = lock(self.as_ptr() as usize).write(); - let value = unsafe { &mut *(self.as_ptr()) }; - let old = *value; - *value = cmp::min(old, val); - old + atomic! { + $t, _a, + { + // TODO: Atomic*::fetch_min requires Rust 1.45. + self.fetch_update(|old| Some(cmp::min(old, val))).unwrap() + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::min(old, val); + old + } } } } }; } -impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);"); -impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);"); -impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);"); -impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);"); -impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);"); -impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);"); +impl_arithmetic!(u8, AtomicU8, "let a = AtomicCell::new(7u8);"); +impl_arithmetic!(i8, AtomicI8, "let a = AtomicCell::new(7i8);"); +impl_arithmetic!(u16, AtomicU16, "let a = AtomicCell::new(7u16);"); +impl_arithmetic!(i16, AtomicI16, "let a = AtomicCell::new(7i16);"); + +impl_arithmetic!(u32, AtomicU32, "let a = AtomicCell::new(7u32);"); +impl_arithmetic!(i32, AtomicI32, "let a = AtomicCell::new(7i32);"); + #[cfg(target_has_atomic = "64")] -impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);"); +impl_arithmetic!(u64, AtomicU64, "let a = AtomicCell::new(7u64);"); #[cfg(target_has_atomic = "64")] -impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);"); +impl_arithmetic!(i64, AtomicI64, "let a = AtomicCell::new(7i64);"); #[cfg(not(target_has_atomic = "64"))] impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);"); #[cfg(not(target_has_atomic = "64"))] impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);"); + // 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!(u128, AtomicU128, "let a = AtomicCell::new(7u128);"); +// impl_arithmetic!(i128, AtomicI128, "let a = AtomicCell::new(7i128);"); impl_arithmetic!(u128, fallback, "let a = AtomicCell::new(7u128);"); impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);"); -impl_arithmetic!( - usize, - atomic::AtomicUsize, - "let a = AtomicCell::new(7usize);" -); -impl_arithmetic!( - isize, - atomic::AtomicIsize, - "let a = AtomicCell::new(7isize);" -); +impl_arithmetic!(usize, AtomicUsize, "let a = AtomicCell::new(7usize);"); +impl_arithmetic!(isize, AtomicIsize, "let a = AtomicCell::new(7isize);"); impl AtomicCell { /// Applies logical "and" to the current value and returns the previous value. @@ -767,8 +824,20 @@ impl AtomicCell { /// ``` #[inline] pub fn fetch_and(&self, val: bool) -> bool { - let a = unsafe { &*(self.as_ptr() as *const AtomicBool) }; - a.fetch_and(val, Ordering::AcqRel) + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_and(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value &= val; + old + } + } } /// Applies logical "nand" to the current value and returns the previous value. @@ -791,8 +860,20 @@ impl AtomicCell { /// ``` #[inline] pub fn fetch_nand(&self, val: bool) -> bool { - let a = unsafe { &*(self.as_ptr() as *const AtomicBool) }; - a.fetch_nand(val, Ordering::AcqRel) + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_nand(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = !(old & val); + old + } + } } /// Applies logical "or" to the current value and returns the previous value. @@ -812,8 +893,20 @@ impl AtomicCell { /// ``` #[inline] pub fn fetch_or(&self, val: bool) -> bool { - let a = unsafe { &*(self.as_ptr() as *const AtomicBool) }; - a.fetch_or(val, Ordering::AcqRel) + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_or(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value |= val; + old + } + } } /// Applies logical "xor" to the current value and returns the previous value. @@ -833,8 +926,20 @@ impl AtomicCell { /// ``` #[inline] pub fn fetch_xor(&self, val: bool) -> bool { - let a = unsafe { &*(self.as_ptr() as *const AtomicBool) }; - a.fetch_xor(val, Ordering::AcqRel) + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_xor(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value ^= val; + old + } + } } } @@ -935,36 +1040,6 @@ impl AtomicUnit { } } -macro_rules! atomic { - // If values of type `$t` can be transmuted into values of the primitive atomic type `$atomic`, - // declares variable `$a` of type `$atomic` and executes `$atomic_op`, breaking out of the loop. - (@check, $t:ty, $atomic:ty, $a:ident, $atomic_op:expr) => { - if can_transmute::<$t, $atomic>() { - let $a: &$atomic; - break $atomic_op; - } - }; - - // If values of type `$t` can be transmuted into values of a primitive atomic type, declares - // variable `$a` of that type and executes `$atomic_op`. Otherwise, just executes - // `$fallback_op`. - ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => { - loop { - atomic!(@check, $t, AtomicUnit, $a, $atomic_op); - - atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); - atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); - atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); - #[cfg(target_has_atomic = "64")] - atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); - // TODO: AtomicU128 is unstable - // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); - - break $fallback_op; - } - }; -} - /// Returns `true` if operations on `AtomicCell` are lock-free. const fn atomic_is_lock_free() -> bool { atomic! { T, _a, true, false } From 17b864467fd359d08309c95e5ee101f3e5f53885 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 Nov 2023 22:17:33 +0900 Subject: [PATCH 18/25] AtomicCell: Use fetch_{min,max} --- crossbeam-utils/src/atomic/atomic_cell.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 7d295b309..7ee1128d1 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -733,8 +733,8 @@ macro_rules! impl_arithmetic { atomic! { $t, _a, { - // TODO: Atomic*::fetch_max requires Rust 1.45. - self.fetch_update(|old| Some(cmp::max(old, val))).unwrap() + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_max(val, Ordering::AcqRel) }, { let _guard = lock(self.as_ptr() as usize).write(); @@ -764,8 +764,8 @@ macro_rules! impl_arithmetic { atomic! { $t, _a, { - // TODO: Atomic*::fetch_min requires Rust 1.45. - self.fetch_update(|old| Some(cmp::min(old, val))).unwrap() + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_min(val, Ordering::AcqRel) }, { let _guard = lock(self.as_ptr() as usize).write(); From e990ee0c23d8249ca3d12af923f4cecebd4e69af Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 13 Dec 2023 10:39:26 +0900 Subject: [PATCH 19/25] epoch: Fix build error with loom --- crossbeam-epoch/src/atomic.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index f6e52ac8c..0dc61021a 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -343,12 +343,21 @@ impl Atomic { /// /// let a = Atomic::::null(); /// ``` + #[cfg(not(crossbeam_loom))] pub const fn null() -> Atomic { Self { data: AtomicUsize::new(0), _marker: PhantomData, } } + /// Returns a new null atomic pointer. + #[cfg(crossbeam_loom)] + pub fn null() -> Atomic { + Self { + data: AtomicUsize::new(0), + _marker: PhantomData, + } + } /// Loads a `Shared` from the atomic pointer. /// From 2ffa481e064b31d568bcdb822b4fcc8e883fc102 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 2 Dec 2023 17:45:37 +0900 Subject: [PATCH 20/25] AtomicCell: Always implement {,Ref}UnwindSafe core::panic::{,Ref}UnwindSafe is available on Rust 1.56+. --- crossbeam-utils/src/atomic/atomic_cell.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 7ee1128d1..165faec76 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -6,12 +6,9 @@ use core::cell::UnsafeCell; use core::cmp; use core::fmt; use core::mem::{self, ManuallyDrop, MaybeUninit}; - +use core::panic::{RefUnwindSafe, UnwindSafe}; use core::ptr; -#[cfg(feature = "std")] -use std::panic::{RefUnwindSafe, UnwindSafe}; - use super::seq_lock::SeqLock; /// A thread-safe mutable memory location. @@ -48,9 +45,7 @@ pub struct AtomicCell { unsafe impl Send for AtomicCell {} unsafe impl Sync for AtomicCell {} -#[cfg(feature = "std")] impl UnwindSafe for AtomicCell {} -#[cfg(feature = "std")] impl RefUnwindSafe for AtomicCell {} impl AtomicCell { From 4df330b8d9e832e119a9a76cdf2363176c9bc02f Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 2 Dec 2023 18:59:09 +0900 Subject: [PATCH 21/25] Catch panics in critical section of thread::scope Replaces https://github.com/crossbeam-rs/crossbeam/pull/724. Co-authored-by: Enkelmann --- crossbeam-utils/src/thread.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crossbeam-utils/src/thread.rs b/crossbeam-utils/src/thread.rs index 74464544a..f71fdea21 100644 --- a/crossbeam-utils/src/thread.rs +++ b/crossbeam-utils/src/thread.rs @@ -152,6 +152,15 @@ pub fn scope<'env, F, R>(f: F) -> thread::Result where F: FnOnce(&Scope<'env>) -> R, { + struct AbortOnPanic; + impl Drop for AbortOnPanic { + fn drop(&mut self) { + if thread::panicking() { + std::process::abort(); + } + } + } + let wg = WaitGroup::new(); let scope = Scope::<'env> { handles: SharedVec::default(), @@ -162,6 +171,10 @@ where // Execute the scoped function, but catch any panics. let result = panic::catch_unwind(panic::AssertUnwindSafe(|| f(&scope))); + // If an unwinding panic occurs before all threads are joined + // promote it to an aborting panic to prevent any threads from escaping the scope. + let guard = AbortOnPanic; + // Wait until all nested scopes are dropped. drop(scope.wait_group); wg.wait(); @@ -177,6 +190,8 @@ where .filter_map(|handle| handle.join().err()) .collect(); + mem::forget(guard); + // If `f` has panicked, resume unwinding. // If any of the child threads have panicked, return the panic errors. // Otherwise, everything is OK and return the result of `f`. From b1e99ecaed8560e01fb42259216250417e77f597 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 2 Dec 2023 21:37:23 +0900 Subject: [PATCH 22/25] Remove dependency on scopeguard --- crossbeam-epoch/Cargo.toml | 1 - crossbeam-epoch/src/guard.rs | 21 ++++++++++++--------- crossbeam-skiplist/Cargo.toml | 4 ---- crossbeam-skiplist/src/base.rs | 10 +++++++--- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index f5c3acf9b..60c525fbc 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -48,7 +48,6 @@ autocfg = "1" [dependencies] cfg-if = "1" memoffset = "0.9" -scopeguard = { version = "1.1", default-features = false } # Enable the use of loom for concurrency testing. # diff --git a/crossbeam-epoch/src/guard.rs b/crossbeam-epoch/src/guard.rs index da1c5c01b..5fe33807c 100644 --- a/crossbeam-epoch/src/guard.rs +++ b/crossbeam-epoch/src/guard.rs @@ -1,8 +1,6 @@ use core::fmt; use core::mem; -use scopeguard::defer; - use crate::atomic::Shared; use crate::collector::Collector; use crate::deferred::Deferred; @@ -366,6 +364,17 @@ impl Guard { where F: FnOnce() -> R, { + // Ensure the Guard is re-pinned even if the function panics + struct ScopeGuard(*const Local); + impl Drop for ScopeGuard { + fn drop(&mut self) { + if let Some(local) = unsafe { self.0.as_ref() } { + mem::forget(local.pin()); + local.release_handle(); + } + } + } + if let Some(local) = unsafe { self.local.as_ref() } { // We need to acquire a handle here to ensure the Local doesn't // disappear from under us. @@ -373,13 +382,7 @@ impl Guard { local.unpin(); } - // Ensure the Guard is re-pinned even if the function panics - defer! { - if let Some(local) = unsafe { self.local.as_ref() } { - mem::forget(local.pin()); - local.release_handle(); - } - } + let _guard = ScopeGuard(self.local); f() } diff --git a/crossbeam-skiplist/Cargo.toml b/crossbeam-skiplist/Cargo.toml index 2a179a5c2..153449544 100644 --- a/crossbeam-skiplist/Cargo.toml +++ b/crossbeam-skiplist/Cargo.toml @@ -41,9 +41,5 @@ version = "0.8.5" path = "../crossbeam-utils" default-features = false -[dependencies.scopeguard] -version = "1.1.0" -default-features = false - [dev-dependencies] rand = "0.8" diff --git a/crossbeam-skiplist/src/base.rs b/crossbeam-skiplist/src/base.rs index 6d5514d81..cc2818fb2 100644 --- a/crossbeam-skiplist/src/base.rs +++ b/crossbeam-skiplist/src/base.rs @@ -937,9 +937,13 @@ where // We failed. Let's search for the key and try again. { // Create a guard that destroys the new node in case search panics. - let sg = scopeguard::guard((), |_| { - Node::finalize(node.as_raw()); - }); + struct ScopeGuard(*const Node); + impl Drop for ScopeGuard { + fn drop(&mut self) { + unsafe { Node::finalize(self.0) } + } + } + let sg = ScopeGuard(node.as_raw()); search = self.search_position(&n.key, guard); mem::forget(sg); } From b0d3521dadc9170be1ada904a04d50caa50f45e7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 13 Dec 2023 10:42:43 +0900 Subject: [PATCH 23/25] ci: Use stable rustc for codegen --- .github/workflows/ci.yml | 2 +- ci/no_atomic.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a626d91d..46cb6cb8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,7 +110,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Rust - run: rustup update nightly && rustup default nightly + run: rustup update stable - run: ci/no_atomic.sh - run: git add -N . && git diff --exit-code if: github.repository_owner != 'crossbeam-rs' || github.event_name != 'schedule' diff --git a/ci/no_atomic.sh b/ci/no_atomic.sh index 44bd008ba..288150b3b 100755 --- a/ci/no_atomic.sh +++ b/ci/no_atomic.sh @@ -11,7 +11,7 @@ cd "$(dirname "$0")"/.. file="no_atomic.rs" no_atomic=() -for target_spec in $(rustc -Z unstable-options --print all-target-specs-json | jq -c '. | to_entries | .[]'); do +for target_spec in $(RUSTC_BOOTSTRAP=1 rustc +stable -Z unstable-options --print all-target-specs-json | jq -c '. | to_entries | .[]'); do target=$(jq <<<"${target_spec}" -r '.key') target_spec=$(jq <<<"${target_spec}" -c '.value') res=$(jq <<<"${target_spec}" -r 'select(."atomic-cas" == false)') From 4657e6e73e8ddec6ca1869cc32acf9cf0c362722 Mon Sep 17 00:00:00 2001 From: Yilin Chen Date: Fri, 16 Dec 2022 00:53:41 +0800 Subject: [PATCH 24/25] Fix get_unchecked UB by raw pointer calculation Signed-off-by: Yilin Chen --- crossbeam-skiplist/src/base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crossbeam-skiplist/src/base.rs b/crossbeam-skiplist/src/base.rs index cc2818fb2..b63183650 100644 --- a/crossbeam-skiplist/src/base.rs +++ b/crossbeam-skiplist/src/base.rs @@ -36,7 +36,7 @@ impl Index for Tower { fn index(&self, index: usize) -> &Atomic> { // This implementation is actually unsafe since we don't check if the // index is in-bounds. But this is fine since this is only used internally. - unsafe { self.pointers.get_unchecked(index) } + unsafe { &*(&self.pointers as *const Atomic>).add(index) } } } From 9449d67d988ab78c06ff30db6d63beb0fa802409 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 13 Dec 2023 22:24:47 +0900 Subject: [PATCH 25/25] Prepare for the next release - crossbeam-channel 0.5.8 -> 0.5.9 - crossbeam-deque 0.8.3 -> 0.8.4 - crossbeam-epoch 0.9.15 -> 0.9.16 - crossbeam-queue 0.3.8 -> 0.3.9 - crossbeam-utils 0.8.16 -> 0.8.17 --- Cargo.toml | 10 +++++----- crossbeam-channel/CHANGELOG.md | 4 ++++ crossbeam-channel/Cargo.toml | 4 ++-- crossbeam-deque/CHANGELOG.md | 4 ++++ crossbeam-deque/Cargo.toml | 6 +++--- crossbeam-epoch/CHANGELOG.md | 8 ++++++++ crossbeam-epoch/Cargo.toml | 4 ++-- crossbeam-queue/CHANGELOG.md | 6 ++++++ crossbeam-queue/Cargo.toml | 4 ++-- crossbeam-skiplist/Cargo.toml | 4 ++-- crossbeam-utils/CHANGELOG.md | 10 ++++++++++ crossbeam-utils/Cargo.toml | 2 +- 12 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b89cb5d7a..c93ca1ff9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,31 +44,31 @@ nightly = ["crossbeam-epoch/nightly", "crossbeam-utils/nightly", "crossbeam-queu cfg-if = "1" [dependencies.crossbeam-channel] -version = "0.5" +version = "0.5.9" path = "./crossbeam-channel" default-features = false optional = true [dependencies.crossbeam-deque] -version = "0.8" +version = "0.8.4" path = "./crossbeam-deque" default-features = false optional = true [dependencies.crossbeam-epoch] -version = "0.9.5" +version = "0.9.16" path = "./crossbeam-epoch" default-features = false optional = true [dependencies.crossbeam-queue] -version = "0.3.2" +version = "0.3.9" path = "./crossbeam-queue" default-features = false optional = true [dependencies.crossbeam-utils] -version = "0.8.5" +version = "0.8.17" path = "./crossbeam-utils" default-features = false diff --git a/crossbeam-channel/CHANGELOG.md b/crossbeam-channel/CHANGELOG.md index 6a405ee73..2dec6ca4c 100644 --- a/crossbeam-channel/CHANGELOG.md +++ b/crossbeam-channel/CHANGELOG.md @@ -1,3 +1,7 @@ +# Version 0.5.9 + +- Bump the minimum supported Rust version to 1.61. (#1037) + # Version 0.5.8 - Fix race condition in unbounded channel. (#972) diff --git a/crossbeam-channel/Cargo.toml b/crossbeam-channel/Cargo.toml index a39e0d767..f8a25a26c 100644 --- a/crossbeam-channel/Cargo.toml +++ b/crossbeam-channel/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-channel" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-channel-X.Y.Z" git tag -version = "0.5.8" +version = "0.5.9" edition = "2018" rust-version = "1.61" license = "MIT OR Apache-2.0" @@ -27,7 +27,7 @@ std = ["crossbeam-utils/std"] cfg-if = "1" [dependencies.crossbeam-utils] -version = "0.8" +version = "0.8.17" path = "../crossbeam-utils" default-features = false optional = true diff --git a/crossbeam-deque/CHANGELOG.md b/crossbeam-deque/CHANGELOG.md index 0937d192f..f763754c2 100644 --- a/crossbeam-deque/CHANGELOG.md +++ b/crossbeam-deque/CHANGELOG.md @@ -1,3 +1,7 @@ +# Version 0.8.4 + +- Bump the minimum supported Rust version to 1.61. (#1037) + # Version 0.8.3 - Add `Stealer::{steal_batch_with_limit, steal_batch_with_limit_and_pop}` methods. (#903) diff --git a/crossbeam-deque/Cargo.toml b/crossbeam-deque/Cargo.toml index c25889c9e..859a57705 100644 --- a/crossbeam-deque/Cargo.toml +++ b/crossbeam-deque/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-deque" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-deque-X.Y.Z" git tag -version = "0.8.3" +version = "0.8.4" edition = "2018" rust-version = "1.61" license = "MIT OR Apache-2.0" @@ -27,13 +27,13 @@ std = ["crossbeam-epoch/std", "crossbeam-utils/std"] cfg-if = "1" [dependencies.crossbeam-epoch] -version = "0.9" +version = "0.9.16" path = "../crossbeam-epoch" default-features = false optional = true [dependencies.crossbeam-utils] -version = "0.8" +version = "0.8.17" path = "../crossbeam-utils" default-features = false optional = true diff --git a/crossbeam-epoch/CHANGELOG.md b/crossbeam-epoch/CHANGELOG.md index f8e7c3c6d..c81580e51 100644 --- a/crossbeam-epoch/CHANGELOG.md +++ b/crossbeam-epoch/CHANGELOG.md @@ -1,3 +1,11 @@ +# Version 0.9.16 + +- Bump the minimum supported Rust version to 1.61. (#1037) +- Improve support for targets without atomic CAS. (#1037) +- Remove build script. (#1037) +- Remove dependency on `scopeguard`. (#1045) +- Update `loom` dependency to 0.7. + # Version 0.9.15 - Update `memoffset` to 0.9. (#981) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 60c525fbc..be4628d03 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-epoch" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-epoch-X.Y.Z" git tag -version = "0.9.15" +version = "0.9.16" edition = "2018" rust-version = "1.61" license = "MIT OR Apache-2.0" @@ -57,7 +57,7 @@ memoffset = "0.9" loom-crate = { package = "loom", version = "0.7.1", optional = true } [dependencies.crossbeam-utils] -version = "0.8.5" +version = "0.8.17" path = "../crossbeam-utils" default-features = false diff --git a/crossbeam-queue/CHANGELOG.md b/crossbeam-queue/CHANGELOG.md index 79aaacdcc..1023c3fa9 100644 --- a/crossbeam-queue/CHANGELOG.md +++ b/crossbeam-queue/CHANGELOG.md @@ -1,3 +1,9 @@ +# Version 0.3.9 + +- Bump the minimum supported Rust version to 1.61. (#1037) +- Improve support for targets without atomic CAS. (#1037) +- Remove build script. (#1037) + # Version 0.3.8 - Fix build script bug introduced in 0.3.7. (#932) diff --git a/crossbeam-queue/Cargo.toml b/crossbeam-queue/Cargo.toml index 0d96de380..3d74523ee 100644 --- a/crossbeam-queue/Cargo.toml +++ b/crossbeam-queue/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-queue" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-queue-X.Y.Z" git tag -version = "0.3.8" +version = "0.3.9" edition = "2018" rust-version = "1.61" license = "MIT OR Apache-2.0" @@ -40,7 +40,7 @@ nightly = ["crossbeam-utils/nightly"] cfg-if = "1" [dependencies.crossbeam-utils] -version = "0.8.5" +version = "0.8.17" path = "../crossbeam-utils" default-features = false diff --git a/crossbeam-skiplist/Cargo.toml b/crossbeam-skiplist/Cargo.toml index 153449544..405bd2f02 100644 --- a/crossbeam-skiplist/Cargo.toml +++ b/crossbeam-skiplist/Cargo.toml @@ -31,13 +31,13 @@ alloc = ["crossbeam-epoch/alloc"] cfg-if = "1" [dependencies.crossbeam-epoch] -version = "0.9.5" +version = "0.9.16" path = "../crossbeam-epoch" default-features = false optional = true [dependencies.crossbeam-utils] -version = "0.8.5" +version = "0.8.17" path = "../crossbeam-utils" default-features = false diff --git a/crossbeam-utils/CHANGELOG.md b/crossbeam-utils/CHANGELOG.md index 4dea4cc33..154169696 100644 --- a/crossbeam-utils/CHANGELOG.md +++ b/crossbeam-utils/CHANGELOG.md @@ -1,3 +1,13 @@ +# Version 0.8.17 + +- Bump the minimum supported Rust version to 1.61. (#1037) +- Improve support for targets without atomic CAS or 64-bit atomic. (#1037) +- Always implement `{,Ref}UnwindSafe` for AtomicCell. (#1045) +- Improve compatibility with Miri, TSan, and loom. (#995, #1003) +- Improve compatibility with unstable `oom=panic`. (#1045) +- Improve implementation of `CachePadded`. (#1014, #1025) +- Update `loom` dependency to 0.7. + # Version 0.8.16 - Improve implementation of `CachePadded`. (#967) diff --git a/crossbeam-utils/Cargo.toml b/crossbeam-utils/Cargo.toml index 294ac97c5..cb16c7e4e 100644 --- a/crossbeam-utils/Cargo.toml +++ b/crossbeam-utils/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-utils" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-utils-X.Y.Z" git tag -version = "0.8.16" +version = "0.8.17" edition = "2018" rust-version = "1.61" license = "MIT OR Apache-2.0"