Skip to content

Commit b664962

Browse files
committed
Make crossbeam-epoch compatible with ThreadSanitizer
1 parent 03532b3 commit b664962

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

ci/tsan

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# TSAN suppressions file for crossbeam
22

3-
# The epoch-based GC uses fences.
4-
race:crossbeam_epoch
5-
63
# Push and steal operations in crossbeam-deque may cause data races, but such
74
# data races are safe. If a data race happens, the value read by `steal` is
85
# forgotten and the steal operation is then retried.

crossbeam-epoch/build.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// The rustc-cfg emitted by the build script are *not* public API.
2+
3+
use std::env;
4+
5+
fn main() {
6+
println!("cargo:rerun-if-changed=build.rs");
7+
8+
// `cfg(sanitize = "..")` is not stabilized.
9+
let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default();
10+
if sanitize.contains("thread") {
11+
println!("cargo:rustc-cfg=crossbeam_sanitize_thread");
12+
}
13+
}

crossbeam-epoch/src/internal.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,18 @@ impl Global {
248248
if local_epoch.is_pinned() && local_epoch.unpinned() != global_epoch {
249249
return global_epoch;
250250
}
251+
252+
// TODO: This is stronger than the actual one because the fence is only emitted
253+
// if the loop is not early exited.
254+
if cfg!(crossbeam_sanitize_thread) {
255+
local.epoch.load(Ordering::Acquire);
256+
}
251257
}
252258
}
253259
}
254-
atomic::fence(Ordering::Acquire);
260+
if !cfg!(crossbeam_sanitize_thread) {
261+
atomic::fence(Ordering::Acquire);
262+
}
255263

256264
// All pinned participants were pinned in the current global epoch.
257265
// Now let's advance the global epoch...

0 commit comments

Comments
 (0)