From b664962d794bb21b3deebd6c35d99731f62f56cc Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 24 Dec 2023 21:19:57 +0900 Subject: [PATCH] Make crossbeam-epoch compatible with ThreadSanitizer --- ci/tsan | 3 --- crossbeam-epoch/build.rs | 13 +++++++++++++ crossbeam-epoch/src/internal.rs | 10 +++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 crossbeam-epoch/build.rs diff --git a/ci/tsan b/ci/tsan index 9ebb04b4f..67fad001a 100644 --- a/ci/tsan +++ b/ci/tsan @@ -1,8 +1,5 @@ # TSAN suppressions file for crossbeam -# The epoch-based GC uses fences. -race:crossbeam_epoch - # Push and steal operations in crossbeam-deque may cause data races, but such # data races are safe. If a data race happens, the value read by `steal` is # forgotten and the steal operation is then retried. diff --git a/crossbeam-epoch/build.rs b/crossbeam-epoch/build.rs new file mode 100644 index 000000000..0395bb7b8 --- /dev/null +++ b/crossbeam-epoch/build.rs @@ -0,0 +1,13 @@ +// The rustc-cfg emitted by the build script are *not* public API. + +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.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-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index bfc706ac3..98e364c17 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -248,10 +248,18 @@ impl Global { if local_epoch.is_pinned() && local_epoch.unpinned() != global_epoch { return global_epoch; } + + // TODO: This is stronger than the actual one because the fence is only emitted + // if the loop is not early exited. + if cfg!(crossbeam_sanitize_thread) { + local.epoch.load(Ordering::Acquire); + } } } } - atomic::fence(Ordering::Acquire); + if !cfg!(crossbeam_sanitize_thread) { + atomic::fence(Ordering::Acquire); + } // All pinned participants were pinned in the current global epoch. // Now let's advance the global epoch...