Skip to content

Commit 4b91729

Browse files
authored
Rollup merge of #65097 - tmiasko:arc, r=Amanieu
Make std::sync::Arc compatible with ThreadSanitizer The memory fences used previously in Arc implementation are not properly understood by thread sanitizer as synchronization primitives. This had unfortunate effect where running any non-trivial program compiled with `-Z sanitizer=thread` would result in numerous false positives. Replace acquire fences with acquire loads to address the issue. Fixes #39608.
2 parents 1057dc9 + fd0e15b commit 4b91729

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#![feature(box_into_raw_non_null)]
8181
#![feature(box_patterns)]
8282
#![feature(box_syntax)]
83+
#![feature(cfg_sanitize)]
8384
#![feature(cfg_target_has_atomic)]
8485
#![feature(coerce_unsized)]
8586
#![feature(const_generic_impls_guard)]

src/liballoc/sync.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ mod tests;
4040
/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
4141
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
4242

43+
#[cfg(not(sanitize = "thread"))]
44+
macro_rules! acquire {
45+
($x:expr) => {
46+
atomic::fence(Acquire)
47+
};
48+
}
49+
50+
// ThreadSanitizer does not support memory fences. To avoid false positive
51+
// reports in Arc / Weak implementation use atomic loads for synchronization
52+
// instead.
53+
#[cfg(sanitize = "thread")]
54+
macro_rules! acquire {
55+
($x:expr) => {
56+
$x.load(Acquire)
57+
};
58+
}
59+
4360
/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
4461
/// Reference Counted'.
4562
///
@@ -402,7 +419,7 @@ impl<T> Arc<T> {
402419
return Err(this);
403420
}
404421

405-
atomic::fence(Acquire);
422+
acquire!(this.inner().strong);
406423

407424
unsafe {
408425
let elem = ptr::read(&this.ptr.as_ref().data);
@@ -739,7 +756,7 @@ impl<T: ?Sized> Arc<T> {
739756
ptr::drop_in_place(&mut self.ptr.as_mut().data);
740757

741758
if self.inner().weak.fetch_sub(1, Release) == 1 {
742-
atomic::fence(Acquire);
759+
acquire!(self.inner().weak);
743760
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
744761
}
745762
}
@@ -1243,7 +1260,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
12431260
//
12441261
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
12451262
// [2]: (https://github.com/rust-lang/rust/pull/41714)
1246-
atomic::fence(Acquire);
1263+
acquire!(self.inner().strong);
12471264

12481265
unsafe {
12491266
self.drop_slow();
@@ -1701,7 +1718,7 @@ impl<T: ?Sized> Drop for Weak<T> {
17011718
let inner = if let Some(inner) = self.inner() { inner } else { return };
17021719

17031720
if inner.weak.fetch_sub(1, Release) == 1 {
1704-
atomic::fence(Acquire);
1721+
acquire!(inner.weak);
17051722
unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) }
17061723
}
17071724
}

0 commit comments

Comments
 (0)