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..8deaef9cb --- /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=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-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index de69a9380..7397aeae5 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -249,10 +249,16 @@ impl Global { if local_epoch.is_pinned() && local_epoch.unpinned() != global_epoch { return global_epoch; } + + 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...