Skip to content

Commit bc1538d

Browse files
committed
Auto merge of rust-lang#3496 - RalfJung:thread-vector-idx, r=RalfJung
global allocations: don't make up a super-high VectorIdx, just use the main thread
2 parents 6b0ce8b + b562faa commit bc1538d

File tree

4 files changed

+50
-48
lines changed

4 files changed

+50
-48
lines changed

src/tools/miri/src/concurrency/data_race.rs

+34-34
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ impl VClockAlloc {
847847
kind: MemoryKind,
848848
current_span: Span,
849849
) -> VClockAlloc {
850+
// Determine the thread that did the allocation, and when it did it.
850851
let (alloc_timestamp, alloc_index) = match kind {
851852
// User allocated and stack memory should track allocation.
852853
MemoryKind::Machine(
@@ -858,21 +859,22 @@ impl VClockAlloc {
858859
| MiriMemoryKind::Mmap,
859860
)
860861
| MemoryKind::Stack => {
861-
let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
862+
let (alloc_index, clocks) = global.active_thread_state(thread_mgr);
862863
let mut alloc_timestamp = clocks.clock[alloc_index];
863864
alloc_timestamp.span = current_span;
864865
(alloc_timestamp, alloc_index)
865866
}
866867
// Other global memory should trace races but be allocated at the 0 timestamp
867-
// (conceptually they are allocated before everything).
868+
// (conceptually they are allocated on the main thread before everything).
868869
MemoryKind::Machine(
869870
MiriMemoryKind::Global
870871
| MiriMemoryKind::Machine
871872
| MiriMemoryKind::Runtime
872873
| MiriMemoryKind::ExternStatic
873874
| MiriMemoryKind::Tls,
874875
)
875-
| MemoryKind::CallerLocation => (VTimestamp::ZERO, VectorIdx::MAX_INDEX),
876+
| MemoryKind::CallerLocation =>
877+
(VTimestamp::ZERO, global.thread_index(ThreadId::MAIN_THREAD)),
876878
};
877879
VClockAlloc {
878880
alloc_ranges: RefCell::new(RangeMap::new(
@@ -930,7 +932,7 @@ impl VClockAlloc {
930932
ptr_dbg: Pointer<AllocId>,
931933
ty: Option<Ty<'_>>,
932934
) -> InterpResult<'tcx> {
933-
let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
935+
let (active_index, active_clocks) = global.active_thread_state(thread_mgr);
934936
let mut other_size = None; // if `Some`, this was a size-mismatch race
935937
let write_clock;
936938
let (other_access, other_thread, other_clock) =
@@ -939,30 +941,30 @@ impl VClockAlloc {
939941
// we are reporting races between two non-atomic reads.
940942
if !access.is_atomic() &&
941943
let Some(atomic) = mem_clocks.atomic() &&
942-
let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
944+
let Some(idx) = Self::find_gt_index(&atomic.write_vector, &active_clocks.clock)
943945
{
944946
(AccessType::AtomicStore, idx, &atomic.write_vector)
945947
} else if !access.is_atomic() &&
946948
let Some(atomic) = mem_clocks.atomic() &&
947-
let Some(idx) = Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
949+
let Some(idx) = Self::find_gt_index(&atomic.read_vector, &active_clocks.clock)
948950
{
949951
(AccessType::AtomicLoad, idx, &atomic.read_vector)
950952
// Then check races with non-atomic writes/reads.
951-
} else if mem_clocks.write.1 > current_clocks.clock[mem_clocks.write.0] {
953+
} else if mem_clocks.write.1 > active_clocks.clock[mem_clocks.write.0] {
952954
write_clock = mem_clocks.write();
953955
(AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock)
954-
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
956+
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &active_clocks.clock) {
955957
(AccessType::NaRead(mem_clocks.read[idx].read_type()), idx, &mem_clocks.read)
956958
// Finally, mixed-size races.
957959
} else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size {
958960
// This is only a race if we are not synchronized with all atomic accesses, so find
959961
// the one we are not synchronized with.
960962
other_size = Some(atomic.size);
961-
if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
963+
if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &active_clocks.clock)
962964
{
963965
(AccessType::AtomicStore, idx, &atomic.write_vector)
964966
} else if let Some(idx) =
965-
Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
967+
Self::find_gt_index(&atomic.read_vector, &active_clocks.clock)
966968
{
967969
(AccessType::AtomicLoad, idx, &atomic.read_vector)
968970
} else {
@@ -975,7 +977,7 @@ impl VClockAlloc {
975977
};
976978

977979
// Load elaborated thread information about the racing thread actions.
978-
let current_thread_info = global.print_thread_metadata(thread_mgr, current_index);
980+
let active_thread_info = global.print_thread_metadata(thread_mgr, active_index);
979981
let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
980982
let involves_non_atomic = !access.is_atomic() || !other_access.is_atomic();
981983

@@ -1003,8 +1005,8 @@ impl VClockAlloc {
10031005
},
10041006
op2: RacingOp {
10051007
action: access.description(ty, other_size.map(|_| access_size)),
1006-
thread_info: current_thread_info,
1007-
span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
1008+
thread_info: active_thread_info,
1009+
span: active_clocks.clock.as_slice()[active_index.index()].span_data(),
10081010
},
10091011
}))?
10101012
}
@@ -1026,7 +1028,7 @@ impl VClockAlloc {
10261028
let current_span = machine.current_span();
10271029
let global = machine.data_race.as_ref().unwrap();
10281030
if global.race_detecting() {
1029-
let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
1031+
let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads);
10301032
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
10311033
for (mem_clocks_range, mem_clocks) in
10321034
alloc_ranges.iter_mut(access_range.start, access_range.size)
@@ -1069,7 +1071,7 @@ impl VClockAlloc {
10691071
let current_span = machine.current_span();
10701072
let global = machine.data_race.as_mut().unwrap();
10711073
if global.race_detecting() {
1072-
let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
1074+
let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads);
10731075
for (mem_clocks_range, mem_clocks) in
10741076
self.alloc_ranges.get_mut().iter_mut(access_range.start, access_range.size)
10751077
{
@@ -1454,7 +1456,7 @@ impl GlobalState {
14541456
// Setup the main-thread since it is not explicitly created:
14551457
// uses vector index and thread-id 0.
14561458
let index = global_state.vector_clocks.get_mut().push(ThreadClockSet::default());
1457-
global_state.vector_info.get_mut().push(ThreadId::new(0));
1459+
global_state.vector_info.get_mut().push(ThreadId::MAIN_THREAD);
14581460
global_state
14591461
.thread_info
14601462
.get_mut()
@@ -1518,7 +1520,7 @@ impl GlobalState {
15181520
thread: ThreadId,
15191521
current_span: Span,
15201522
) {
1521-
let current_index = self.current_index(thread_mgr);
1523+
let current_index = self.active_thread_index(thread_mgr);
15221524

15231525
// Enable multi-threaded execution, there are now at least two threads
15241526
// so data-races are now possible.
@@ -1642,7 +1644,7 @@ impl GlobalState {
16421644
/// `thread_joined`.
16431645
#[inline]
16441646
pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) {
1645-
let current_index = self.current_index(thread_mgr);
1647+
let current_index = self.active_thread_index(thread_mgr);
16461648

16471649
// Increment the clock to a unique termination timestamp.
16481650
let vector_clocks = self.vector_clocks.get_mut();
@@ -1680,9 +1682,9 @@ impl GlobalState {
16801682
op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
16811683
) -> InterpResult<'tcx> {
16821684
if self.multi_threaded.get() {
1683-
let (index, clocks) = self.current_thread_state_mut(thread_mgr);
1685+
let (index, clocks) = self.active_thread_state_mut(thread_mgr);
16841686
if op(index, clocks)? {
1685-
let (_, mut clocks) = self.current_thread_state_mut(thread_mgr);
1687+
let (_, mut clocks) = self.active_thread_state_mut(thread_mgr);
16861688
clocks.increment_clock(index, current_span);
16871689
}
16881690
}
@@ -1725,13 +1727,15 @@ impl GlobalState {
17251727
Ref::map(clocks, |c| &c.clock)
17261728
}
17271729

1730+
fn thread_index(&self, thread: ThreadId) -> VectorIdx {
1731+
self.thread_info.borrow()[thread].vector_index.expect("thread has no assigned vector")
1732+
}
1733+
17281734
/// Load the vector index used by the given thread as well as the set of vector clocks
17291735
/// used by the thread.
17301736
#[inline]
17311737
fn thread_state_mut(&self, thread: ThreadId) -> (VectorIdx, RefMut<'_, ThreadClockSet>) {
1732-
let index = self.thread_info.borrow()[thread]
1733-
.vector_index
1734-
.expect("Loading thread state for thread with no assigned vector");
1738+
let index = self.thread_index(thread);
17351739
let ref_vector = self.vector_clocks.borrow_mut();
17361740
let clocks = RefMut::map(ref_vector, |vec| &mut vec[index]);
17371741
(index, clocks)
@@ -1741,9 +1745,7 @@ impl GlobalState {
17411745
/// used by the thread.
17421746
#[inline]
17431747
fn thread_state(&self, thread: ThreadId) -> (VectorIdx, Ref<'_, ThreadClockSet>) {
1744-
let index = self.thread_info.borrow()[thread]
1745-
.vector_index
1746-
.expect("Loading thread state for thread with no assigned vector");
1748+
let index = self.thread_index(thread);
17471749
let ref_vector = self.vector_clocks.borrow();
17481750
let clocks = Ref::map(ref_vector, |vec| &vec[index]);
17491751
(index, clocks)
@@ -1752,7 +1754,7 @@ impl GlobalState {
17521754
/// Load the current vector clock in use and the current set of thread clocks
17531755
/// in use for the vector.
17541756
#[inline]
1755-
pub(super) fn current_thread_state(
1757+
pub(super) fn active_thread_state(
17561758
&self,
17571759
thread_mgr: &ThreadManager<'_, '_>,
17581760
) -> (VectorIdx, Ref<'_, ThreadClockSet>) {
@@ -1762,7 +1764,7 @@ impl GlobalState {
17621764
/// Load the current vector clock in use and the current set of thread clocks
17631765
/// in use for the vector mutably for modification.
17641766
#[inline]
1765-
pub(super) fn current_thread_state_mut(
1767+
pub(super) fn active_thread_state_mut(
17661768
&self,
17671769
thread_mgr: &ThreadManager<'_, '_>,
17681770
) -> (VectorIdx, RefMut<'_, ThreadClockSet>) {
@@ -1772,22 +1774,20 @@ impl GlobalState {
17721774
/// Return the current thread, should be the same
17731775
/// as the data-race active thread.
17741776
#[inline]
1775-
fn current_index(&self, thread_mgr: &ThreadManager<'_, '_>) -> VectorIdx {
1777+
fn active_thread_index(&self, thread_mgr: &ThreadManager<'_, '_>) -> VectorIdx {
17761778
let active_thread_id = thread_mgr.get_active_thread_id();
1777-
self.thread_info.borrow()[active_thread_id]
1778-
.vector_index
1779-
.expect("active thread has no assigned vector")
1779+
self.thread_index(active_thread_id)
17801780
}
17811781

17821782
// SC ATOMIC STORE rule in the paper.
17831783
pub(super) fn sc_write(&self, thread_mgr: &ThreadManager<'_, '_>) {
1784-
let (index, clocks) = self.current_thread_state(thread_mgr);
1784+
let (index, clocks) = self.active_thread_state(thread_mgr);
17851785
self.last_sc_write.borrow_mut().set_at_index(&clocks.clock, index);
17861786
}
17871787

17881788
// SC ATOMIC READ rule in the paper.
17891789
pub(super) fn sc_read(&self, thread_mgr: &ThreadManager<'_, '_>) {
1790-
let (.., mut clocks) = self.current_thread_state_mut(thread_mgr);
1790+
let (.., mut clocks) = self.active_thread_state_mut(thread_mgr);
17911791
clocks.read_seqcst.join(&self.last_sc_fence.borrow());
17921792
}
17931793
}

src/tools/miri/src/concurrency/thread.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ impl ThreadId {
5757
pub fn to_u32(self) -> u32 {
5858
self.0
5959
}
60+
61+
pub const MAIN_THREAD: ThreadId = ThreadId(0);
6062
}
6163

6264
impl Idx for ThreadId {
@@ -401,7 +403,7 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
401403
// Create the main thread and add it to the list of threads.
402404
threads.push(Thread::new(Some("main"), None));
403405
Self {
404-
active_thread: ThreadId::new(0),
406+
active_thread: ThreadId::MAIN_THREAD,
405407
threads,
406408
sync: SynchronizationState::default(),
407409
thread_local_alloc_ids: Default::default(),
@@ -416,10 +418,12 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
416418
ecx: &mut MiriInterpCx<'mir, 'tcx>,
417419
on_main_stack_empty: StackEmptyCallback<'mir, 'tcx>,
418420
) {
419-
ecx.machine.threads.threads[ThreadId::new(0)].on_stack_empty = Some(on_main_stack_empty);
421+
ecx.machine.threads.threads[ThreadId::MAIN_THREAD].on_stack_empty =
422+
Some(on_main_stack_empty);
420423
if ecx.tcx.sess.target.os.as_ref() != "windows" {
421424
// The main thread can *not* be joined on except on windows.
422-
ecx.machine.threads.threads[ThreadId::new(0)].join_status = ThreadJoinStatus::Detached;
425+
ecx.machine.threads.threads[ThreadId::MAIN_THREAD].join_status =
426+
ThreadJoinStatus::Detached;
423427
}
424428
}
425429

src/tools/miri/src/concurrency/vector_clock.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ use super::data_race::NaReadType;
1313
/// but in some cases one vector index may be shared with
1414
/// multiple thread ids if it's safe to do so.
1515
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
16-
pub struct VectorIdx(u32);
16+
pub(super) struct VectorIdx(u32);
1717

1818
impl VectorIdx {
1919
#[inline(always)]
20-
pub fn to_u32(self) -> u32 {
20+
fn to_u32(self) -> u32 {
2121
self.0
2222
}
23-
24-
pub const MAX_INDEX: VectorIdx = VectorIdx(u32::MAX);
2523
}
2624

2725
impl Idx for VectorIdx {
@@ -51,7 +49,7 @@ const SMALL_VECTOR: usize = 4;
5149
/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
5250
/// so that diagnostics can report what code was responsible for an operation.
5351
#[derive(Clone, Copy, Debug)]
54-
pub struct VTimestamp {
52+
pub(super) struct VTimestamp {
5553
/// The lowest bit indicates read type, the rest is the time.
5654
/// `1` indicates a retag read, `0` a regular read.
5755
time_and_read_type: u32,
@@ -87,7 +85,7 @@ impl VTimestamp {
8785
}
8886

8987
#[inline]
90-
pub fn read_type(&self) -> NaReadType {
88+
pub(super) fn read_type(&self) -> NaReadType {
9189
if self.time_and_read_type & 1 == 0 { NaReadType::Read } else { NaReadType::Retag }
9290
}
9391

@@ -97,7 +95,7 @@ impl VTimestamp {
9795
}
9896

9997
#[inline]
100-
pub fn span_data(&self) -> SpanData {
98+
pub(super) fn span_data(&self) -> SpanData {
10199
self.span.data()
102100
}
103101
}

src/tools/miri/src/concurrency/weak_memory.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
270270
) {
271271
let store_elem = self.buffer.back();
272272
if let Some(store_elem) = store_elem {
273-
let (index, clocks) = global.current_thread_state(thread_mgr);
273+
let (index, clocks) = global.active_thread_state(thread_mgr);
274274
store_elem.load_impl(index, &clocks, is_seqcst);
275275
}
276276
}
@@ -289,7 +289,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
289289
let (store_elem, recency) = {
290290
// The `clocks` we got here must be dropped before calling validate_atomic_load
291291
// as the race detector will update it
292-
let (.., clocks) = global.current_thread_state(thread_mgr);
292+
let (.., clocks) = global.active_thread_state(thread_mgr);
293293
// Load from a valid entry in the store buffer
294294
self.fetch_store(is_seqcst, &clocks, &mut *rng)
295295
};
@@ -300,7 +300,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
300300
// requires access to ThreadClockSet.clock, which is updated by the race detector
301301
validate()?;
302302

303-
let (index, clocks) = global.current_thread_state(thread_mgr);
303+
let (index, clocks) = global.active_thread_state(thread_mgr);
304304
let loaded = store_elem.load_impl(index, &clocks, is_seqcst);
305305
Ok((loaded, recency))
306306
}
@@ -312,7 +312,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
312312
thread_mgr: &ThreadManager<'_, '_>,
313313
is_seqcst: bool,
314314
) -> InterpResult<'tcx> {
315-
let (index, clocks) = global.current_thread_state(thread_mgr);
315+
let (index, clocks) = global.active_thread_state(thread_mgr);
316316

317317
self.store_impl(val, index, &clocks.clock, is_seqcst);
318318
Ok(())

0 commit comments

Comments
 (0)