fix data race in ReentrantLock fallback for targets without 64bit atomics
This commit is contained in:
@@ -136,7 +136,7 @@ cfg_if!(
|
|||||||
// we only ever read from the tid if `tls_addr` matches the current
|
// we only ever read from the tid if `tls_addr` matches the current
|
||||||
// TLS address. In that case, either the tid has been set by
|
// TLS address. In that case, either the tid has been set by
|
||||||
// the current thread, or by a thread that has terminated before
|
// the current thread, or by a thread that has terminated before
|
||||||
// the current thread was created. In either case, no further
|
// the current thread's `tls_addr` was allocated. In either case, no further
|
||||||
// synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
|
// synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
|
||||||
tls_addr: Atomic<usize>,
|
tls_addr: Atomic<usize>,
|
||||||
tid: UnsafeCell<u64>,
|
tid: UnsafeCell<u64>,
|
||||||
@@ -154,8 +154,12 @@ cfg_if!(
|
|||||||
// NOTE: This assumes that `owner` is the ID of the current
|
// NOTE: This assumes that `owner` is the ID of the current
|
||||||
// thread, and may spuriously return `false` if that's not the case.
|
// thread, and may spuriously return `false` if that's not the case.
|
||||||
fn contains(&self, owner: ThreadId) -> bool {
|
fn contains(&self, owner: ThreadId) -> bool {
|
||||||
|
// We must call `tls_addr()` *before* doing the load to ensure that if we reuse an
|
||||||
|
// earlier thread's address, the `tls_addr.load()` below happens-after everything
|
||||||
|
// that thread did.
|
||||||
|
let tls_addr = tls_addr();
|
||||||
// SAFETY: See the comments in the struct definition.
|
// SAFETY: See the comments in the struct definition.
|
||||||
self.tls_addr.load(Ordering::Relaxed) == tls_addr()
|
self.tls_addr.load(Ordering::Relaxed) == tls_addr
|
||||||
&& unsafe { *self.tid.get() } == owner.as_u64().get()
|
&& unsafe { *self.tid.get() } == owner.as_u64().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
src/tools/miri/tests/many-seeds/reentrant-lock.rs
Normal file
19
src/tools/miri/tests/many-seeds/reentrant-lock.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#![feature(reentrant_lock)]
|
||||||
|
//! This is a regression test for
|
||||||
|
//! <https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/reentrant.20lock.20failure.20on.20musl>.
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::sync::ReentrantLock;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
static LOCK: ReentrantLock<Cell<i32>> = ReentrantLock::new(Cell::new(0));
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for _ in 0..20 {
|
||||||
|
thread::spawn(move || {
|
||||||
|
let val = LOCK.lock();
|
||||||
|
val.set(val.get() + 1);
|
||||||
|
drop(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user