From d1184ae58d8791f424cab2101b1c67f176423e75 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 30 Oct 2022 21:04:00 -0400 Subject: [PATCH] Include a Span in VClock --- src/tools/miri/src/concurrency/data_race.rs | 169 +++++++++++------- src/tools/miri/src/concurrency/init_once.rs | 6 +- src/tools/miri/src/concurrency/sync.rs | 33 +++- src/tools/miri/src/concurrency/thread.rs | 12 +- .../miri/src/concurrency/vector_clock.rs | 90 ++++++++-- src/tools/miri/src/concurrency/weak_memory.rs | 2 +- src/tools/miri/src/diagnostics.rs | 26 ++- src/tools/miri/src/machine.rs | 1 + .../fail/data_race/alloc_read_race.stderr | 10 ++ .../fail/data_race/alloc_write_race.stderr | 10 ++ .../atomic_read_na_write_race1.stderr | 10 ++ .../atomic_read_na_write_race2.stderr | 10 ++ .../atomic_write_na_read_race1.stderr | 10 ++ .../atomic_write_na_read_race2.stderr | 10 ++ .../atomic_write_na_write_race1.stderr | 10 ++ .../atomic_write_na_write_race2.stderr | 10 ++ .../dangling_thread_async_race.stderr | 10 ++ .../data_race/dangling_thread_race.stderr | 10 ++ .../fail/data_race/dealloc_read_race1.stderr | 15 ++ .../data_race/dealloc_read_race_stack.stderr | 10 ++ .../fail/data_race/dealloc_write_race1.stderr | 15 ++ .../data_race/dealloc_write_race_stack.stderr | 10 ++ .../enable_after_join_to_main.stderr | 10 ++ .../fail/data_race/fence_after_load.stderr | 10 ++ .../fail/data_race/read_write_race.stderr | 10 ++ .../data_race/read_write_race_stack.stderr | 10 ++ .../fail/data_race/relax_acquire_race.stderr | 10 ++ .../fail/data_race/release_seq_race.stderr | 10 ++ .../release_seq_race_same_thread.stderr | 10 ++ .../miri/tests/fail/data_race/rmw_race.stderr | 10 ++ .../fail/data_race/stack_pop_race.stderr | 10 ++ .../fail/data_race/write_write_race.stderr | 10 ++ .../data_race/write_write_race_stack.stderr | 10 ++ .../retag_data_race_read.stderr | 10 ++ .../retag_data_race_write.stderr | 10 ++ 35 files changed, 531 insertions(+), 88 deletions(-) diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index bcbf45a3d24..8b343dd2fe8 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -50,8 +50,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir; +use rustc_span::Span; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, Size}; +use crate::diagnostics::RacingOp; use crate::*; use super::{ @@ -144,8 +147,8 @@ fn apply_acquire_fence(&mut self) { /// Increment the happens-before clock at a /// known index. #[inline] - fn increment_clock(&mut self, index: VectorIdx) { - self.clock.increment_index(index); + fn increment_clock(&mut self, index: VectorIdx, current_span: Span) { + self.clock.increment_index(index, current_span); } /// Join the happens-before clock with that of @@ -361,6 +364,8 @@ fn atomic_read_detect( atomic.read_vector.set_at_index(&clocks.clock, index); Ok(()) } else { + let atomic = self.atomic_mut(); + atomic.read_vector.set_at_index(&clocks.clock, index); Err(DataRace) } } @@ -378,6 +383,8 @@ fn atomic_write_detect( atomic.write_vector.set_at_index(&clocks.clock, index); Ok(()) } else { + let atomic = self.atomic_mut(); + atomic.write_vector.set_at_index(&clocks.clock, index); Err(DataRace) } } @@ -386,46 +393,51 @@ fn atomic_write_detect( /// returns true if a data-race is detected. fn read_race_detect( &mut self, - clocks: &ThreadClockSet, + clocks: &mut ThreadClockSet, index: VectorIdx, + current_span: Span, ) -> Result<(), DataRace> { log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks); - if self.write <= clocks.clock[self.write_index] { + let res = if self.write <= clocks.clock[self.write_index] { let race_free = if let Some(atomic) = self.atomic() { atomic.write_vector <= clocks.clock } else { true }; - if race_free { - self.read.set_at_index(&clocks.clock, index); - Ok(()) - } else { - Err(DataRace) - } + self.read.set_at_index(&clocks.clock, index); + if race_free { Ok(()) } else { Err(DataRace) } } else { Err(DataRace) + }; + if res.is_ok() && current_span != DUMMY_SP { + clocks.clock[index].span = current_span; } + res } /// Detect races for non-atomic write operations at the current memory cell /// returns true if a data-race is detected. fn write_race_detect( &mut self, - clocks: &ThreadClockSet, + clocks: &mut ThreadClockSet, index: VectorIdx, write_type: WriteType, + current_span: Span, ) -> Result<(), DataRace> { log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks); + if current_span != DUMMY_SP { + clocks.clock[index].span = current_span; + } if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock { let race_free = if let Some(atomic) = self.atomic() { atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock } else { true }; + self.write = clocks.clock[index]; + self.write_index = index; + self.write_type = write_type; if race_free { - self.write = clocks.clock[index]; - self.write_index = index; - self.write_type = write_type; self.read.set_zero_vector(); Ok(()) } else { @@ -621,30 +633,35 @@ fn atomic_compare_exchange_scalar( /// Update the data-race detector for an atomic fence on the current thread. fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> { let this = self.eval_context_mut(); + let current_span = this.machine.current_span(); if let Some(data_race) = &mut this.machine.data_race { - data_race.maybe_perform_sync_operation(&this.machine.threads, |index, mut clocks| { - log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic); + data_race.maybe_perform_sync_operation( + &this.machine.threads, + |index, mut clocks| { + log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic); - // Apply data-race detection for the current fences - // this treats AcqRel and SeqCst as the same as an acquire - // and release fence applied in the same timestamp. - if atomic != AtomicFenceOrd::Release { - // Either Acquire | AcqRel | SeqCst - clocks.apply_acquire_fence(); - } - if atomic != AtomicFenceOrd::Acquire { - // Either Release | AcqRel | SeqCst - clocks.apply_release_fence(); - } - if atomic == AtomicFenceOrd::SeqCst { - data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index); - clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow()); - clocks.write_seqcst.join(&data_race.last_sc_write.borrow()); - } + // Apply data-race detection for the current fences + // this treats AcqRel and SeqCst as the same as an acquire + // and release fence applied in the same timestamp. + if atomic != AtomicFenceOrd::Release { + // Either Acquire | AcqRel | SeqCst + clocks.apply_acquire_fence(); + } + if atomic != AtomicFenceOrd::Acquire { + // Either Release | AcqRel | SeqCst + clocks.apply_release_fence(); + } + if atomic == AtomicFenceOrd::SeqCst { + data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index); + clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow()); + clocks.write_seqcst.join(&data_race.last_sc_write.borrow()); + } - // Increment timestamp in case of release semantics. - Ok(atomic != AtomicFenceOrd::Acquire) - }) + // Increment timestamp in case of release semantics. + Ok(atomic != AtomicFenceOrd::Acquire) + }, + current_span, + ) } else { Ok(()) } @@ -682,6 +699,7 @@ pub fn new_allocation( thread_mgr: &ThreadManager<'_, '_>, len: Size, kind: MemoryKind, + current_span: Span, ) -> VClockAlloc { let (alloc_timestamp, alloc_index) = match kind { // User allocated and stack memory should track allocation. @@ -693,7 +711,10 @@ pub fn new_allocation( ) | MemoryKind::Stack => { let (alloc_index, clocks) = global.current_thread_state(thread_mgr); - let alloc_timestamp = clocks.clock[alloc_index]; + let mut alloc_timestamp = clocks.clock[alloc_index]; + if current_span != DUMMY_SP { + alloc_timestamp.span = current_span; + } (alloc_timestamp, alloc_index) } // Other global memory should trace races but be allocated at the 0 timestamp. @@ -704,7 +725,7 @@ pub fn new_allocation( | MiriMemoryKind::ExternStatic | MiriMemoryKind::Tls, ) - | MemoryKind::CallerLocation => (0, VectorIdx::MAX_INDEX), + | MemoryKind::CallerLocation => (VTimestamp::NONE, VectorIdx::MAX_INDEX), }; VClockAlloc { alloc_ranges: RefCell::new(RangeMap::new( @@ -735,7 +756,7 @@ fn find_gt_index(l: &VClock, r: &VClock) -> Option { let idx = l_remainder_slice .iter() .enumerate() - .find_map(|(idx, &r)| if r == 0 { None } else { Some(idx) }) + .find_map(|(idx, &r)| if r == VTimestamp::NONE { None } else { Some(idx) }) .expect("Invalid VClock Invariant"); Some(idx + r_slice.len()) } else { @@ -762,7 +783,7 @@ fn report_data_race<'tcx>( ) -> InterpResult<'tcx> { let (current_index, current_clocks) = global.current_thread_state(thread_mgr); let write_clock; - let (other_action, other_thread, _other_clock) = if range.write + let (other_action, other_thread, other_clock) = if range.write > current_clocks.clock[range.write_index] { // Convert the write action into the vector clock it @@ -799,14 +820,19 @@ fn report_data_race<'tcx>( let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread); // Throw the data-race detection. - throw_ub_format!( - "Data race detected between {} on {} and {} on {} at {:?}", - action, - current_thread_info, - other_action, - other_thread_info, - ptr_dbg, - ) + Err(err_machine_stop!(TerminationInfo::DataRace { + ptr: ptr_dbg, + op1: RacingOp { + action: action.to_string(), + thread_info: current_thread_info, + span: current_clocks.clock.as_slice()[current_index.index()].span_data(), + }, + op2: RacingOp { + action: other_action.to_string(), + thread_info: other_thread_info, + span: other_clock.as_slice()[other_thread.index()].span_data(), + }, + }))? } /// Detect racing atomic read and writes (not data races) @@ -840,12 +866,14 @@ pub fn read<'tcx>( range: AllocRange, machine: &MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { + let current_span = machine.current_span(); let global = machine.data_race.as_ref().unwrap(); if global.race_detecting() { - let (index, clocks) = global.current_thread_state(&machine.threads); + let (index, mut clocks) = global.current_thread_state_mut(&machine.threads); let mut alloc_ranges = self.alloc_ranges.borrow_mut(); for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) { - if let Err(DataRace) = range.read_race_detect(&clocks, index) { + if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) { + drop(clocks); // Report data-race. return Self::report_data_race( global, @@ -871,11 +899,15 @@ fn unique_access<'tcx>( write_type: WriteType, machine: &mut MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { + let current_span = machine.current_span(); let global = machine.data_race.as_mut().unwrap(); if global.race_detecting() { - let (index, clocks) = global.current_thread_state(&machine.threads); + let (index, mut clocks) = global.current_thread_state_mut(&machine.threads); for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) { - if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) { + if let Err(DataRace) = + range.write_race_detect(&mut clocks, index, write_type, current_span) + { + drop(clocks); // Report data-race return Self::report_data_race( global, @@ -1100,6 +1132,7 @@ fn validate_atomic_op( size.bytes() ); + let current_span = this.machine.current_span(); // Perform the atomic operation. data_race.maybe_perform_sync_operation( &this.machine.threads, @@ -1124,6 +1157,7 @@ fn validate_atomic_op( // This conservatively assumes all operations have release semantics Ok(true) }, + current_span, )?; // Log changes to atomic memory. @@ -1303,7 +1337,12 @@ fn find_vector_index_reuse_candidate(&self) -> Option { // Hook for thread creation, enabled multi-threaded execution and marks // the current thread timestamp as happening-before the current thread. #[inline] - pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: ThreadId) { + pub fn thread_created( + &mut self, + thread_mgr: &ThreadManager<'_, '_>, + thread: ThreadId, + current_span: Span, + ) { let current_index = self.current_index(thread_mgr); // Enable multi-threaded execution, there are now at least two threads @@ -1320,7 +1359,7 @@ pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: Thr // Now re-configure the re-use candidate, increment the clock // for the new sync use of the vector. let vector_clocks = self.vector_clocks.get_mut(); - vector_clocks[reuse_index].increment_clock(reuse_index); + vector_clocks[reuse_index].increment_clock(reuse_index, current_span); // Locate the old thread the vector was associated with and update // it to represent the new thread instead. @@ -1360,8 +1399,8 @@ pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: Thr // Advance both threads after the synchronized operation. // Both operations are considered to have release semantics. - current.increment_clock(current_index); - created.increment_clock(created_index); + current.increment_clock(current_index, current_span); + created.increment_clock(created_index, current_span); } /// Hook on a thread join to update the implicit happens-before relation between the joined @@ -1427,13 +1466,13 @@ pub fn thread_joined( /// This should be called strictly before any calls to /// `thread_joined`. #[inline] - pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) { + pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) { let current_index = self.current_index(thread_mgr); // Increment the clock to a unique termination timestamp. let vector_clocks = self.vector_clocks.get_mut(); let current_clocks = &mut vector_clocks[current_index]; - current_clocks.increment_clock(current_index); + current_clocks.increment_clock(current_index, current_span); // Load the current thread id for the executing vector. let vector_info = self.vector_info.get_mut(); @@ -1463,12 +1502,13 @@ fn maybe_perform_sync_operation<'tcx>( &self, thread_mgr: &ThreadManager<'_, '_>, op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>, + current_span: Span, ) -> InterpResult<'tcx> { if self.multi_threaded.get() { let (index, clocks) = self.current_thread_state_mut(thread_mgr); if op(index, clocks)? { let (_, mut clocks) = self.current_thread_state_mut(thread_mgr); - clocks.increment_clock(index); + clocks.increment_clock(index, current_span); } } Ok(()) @@ -1501,10 +1541,10 @@ pub fn validate_lock_acquire(&self, lock: &VClock, thread: ThreadId) { /// since an acquire operation should have occurred before, however /// for futex & condvar operations this is not the case and this /// operation must be used. - pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) { + pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId, current_span: Span) { let (index, mut clocks) = self.load_thread_state_mut(thread); lock.clone_from(&clocks.clock); - clocks.increment_clock(index); + clocks.increment_clock(index, current_span); } /// Release a lock handle, express that this happens-before @@ -1514,10 +1554,15 @@ pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) { /// For normal locks this should be equivalent to `validate_lock_release`. /// This function only exists for joining over the set of concurrent readers /// in a read-write lock and should not be used for anything else. - pub fn validate_lock_release_shared(&self, lock: &mut VClock, thread: ThreadId) { + pub fn validate_lock_release_shared( + &self, + lock: &mut VClock, + thread: ThreadId, + current_span: Span, + ) { let (index, mut clocks) = self.load_thread_state_mut(thread); lock.join(&clocks.clock); - clocks.increment_clock(index); + clocks.increment_clock(index, current_span); } /// Load the vector index used by the given thread as well as the set of vector clocks diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 9c9d505297c..867683d3552 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -160,6 +160,7 @@ fn init_once_begin(&mut self, id: InitOnceId) { fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let current_thread = this.get_active_thread(); + let current_span = this.machine.current_span(); let init_once = &mut this.machine.threads.sync.init_onces[id]; assert_eq!( @@ -172,7 +173,7 @@ fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> { // Each complete happens-before the end of the wait if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_release(&mut init_once.data_race, current_thread); + data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span); } // Wake up everyone. @@ -188,6 +189,7 @@ fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> { fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let current_thread = this.get_active_thread(); + let current_span = this.machine.current_span(); let init_once = &mut this.machine.threads.sync.init_onces[id]; assert_eq!( init_once.status, @@ -197,7 +199,7 @@ fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> { // Each complete happens-before the end of the wait if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_release(&mut init_once.data_race, current_thread); + data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span); } // Wake up one waiting thread, so they can go ahead and try to init this. diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 402c9ce6fc9..b9620523974 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -359,6 +359,7 @@ fn mutex_lock(&mut self, id: MutexId, thread: ThreadId) { /// return `None`. fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option { let this = self.eval_context_mut(); + let current_span = this.machine.current_span(); let mutex = &mut this.machine.threads.sync.mutexes[id]; if let Some(current_owner) = mutex.owner { // Mutex is locked. @@ -375,7 +376,11 @@ fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option bool { let this = self.eval_context_mut(); + let current_span = this.machine.current_span(); let rwlock = &mut this.machine.threads.sync.rwlocks[id]; match rwlock.readers.entry(reader) { Entry::Occupied(mut entry) => { @@ -470,7 +476,11 @@ fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool { Entry::Vacant(_) => return false, // we did not even own this lock } if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_release_shared(&mut rwlock.data_race_reader, reader); + data_race.validate_lock_release_shared( + &mut rwlock.data_race_reader, + reader, + current_span, + ); } // The thread was a reader. If the lock is not held any more, give it to a writer. @@ -511,6 +521,7 @@ fn rwlock_writer_lock(&mut self, id: RwLockId, writer: ThreadId) { #[inline] fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> bool { let this = self.eval_context_mut(); + let current_span = this.machine.current_span(); let rwlock = &mut this.machine.threads.sync.rwlocks[id]; if let Some(current_writer) = rwlock.writer { if current_writer != expected_writer { @@ -523,8 +534,16 @@ fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> b // since this writer happens-before both the union of readers once they are finished // and the next writer if let Some(data_race) = &this.machine.data_race { - data_race.validate_lock_release(&mut rwlock.data_race, current_writer); - data_race.validate_lock_release(&mut rwlock.data_race_reader, current_writer); + data_race.validate_lock_release( + &mut rwlock.data_race, + current_writer, + current_span, + ); + data_race.validate_lock_release( + &mut rwlock.data_race_reader, + current_writer, + current_span, + ); } // The thread was a writer. // @@ -595,12 +614,13 @@ fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, lock: CondvarLock) { fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> { let this = self.eval_context_mut(); let current_thread = this.get_active_thread(); + let current_span = this.machine.current_span(); let condvar = &mut this.machine.threads.sync.condvars[id]; let data_race = &this.machine.data_race; // Each condvar signal happens-before the end of the condvar wake if let Some(data_race) = data_race { - data_race.validate_lock_release(&mut condvar.data_race, current_thread); + data_race.validate_lock_release(&mut condvar.data_race, current_thread, current_span); } condvar.waiters.pop_front().map(|waiter| { if let Some(data_race) = data_race { @@ -628,12 +648,13 @@ fn futex_wait(&mut self, addr: u64, thread: ThreadId, bitset: u32) { fn futex_wake(&mut self, addr: u64, bitset: u32) -> Option { let this = self.eval_context_mut(); let current_thread = this.get_active_thread(); + let current_span = this.machine.current_span(); let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?; let data_race = &this.machine.data_race; // Each futex-wake happens-before the end of the futex wait if let Some(data_race) = data_race { - data_race.validate_lock_release(&mut futex.data_race, current_thread); + data_race.validate_lock_release(&mut futex.data_race, current_thread, current_span); } // Wake up the first thread in the queue that matches any of the bits in the bitset. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 03f9ed351fb..9173eb3c4ee 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -13,6 +13,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::Mutability; use rustc_middle::ty::layout::TyAndLayout; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use crate::concurrency::data_race; @@ -617,6 +618,7 @@ fn get_ready_callback( fn thread_terminated( &mut self, mut data_race: Option<&mut data_race::GlobalState>, + current_span: Span, ) -> Vec> { let mut free_tls_statics = Vec::new(); { @@ -634,7 +636,7 @@ fn thread_terminated( } // Set the thread into a terminated state in the data-race detector. if let Some(ref mut data_race) = data_race { - data_race.thread_terminated(self); + data_race.thread_terminated(self, current_span); } // Check if we need to unblock any threads. let mut joined_threads = vec![]; // store which threads joined, we'll need it @@ -813,8 +815,9 @@ fn start_regular_thread( let mut state = tls::TlsDtorsState::default(); Box::new(move |m| state.on_stack_empty(m)) }); + let current_span = this.machine.current_span(); if let Some(data_race) = &mut this.machine.data_race { - data_race.thread_created(&this.machine.threads, new_thread_id); + data_race.thread_created(&this.machine.threads, new_thread_id, current_span); } // Write the current thread-id, switch to the next thread later @@ -1041,7 +1044,10 @@ fn terminate_active_thread(&mut self) -> InterpResult<'tcx> { assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated"); thread.state = ThreadState::Terminated; - for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) { + let current_span = this.machine.current_span(); + for ptr in + this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span) + { this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?; } Ok(()) diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index ba04991a588..191bb1449af 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -1,6 +1,11 @@ use rustc_index::vec::Idx; +use rustc_span::{Span, SpanData, DUMMY_SP}; use smallvec::SmallVec; -use std::{cmp::Ordering, fmt::Debug, ops::Index}; +use std::{ + cmp::Ordering, + fmt::Debug, + ops::{Index, IndexMut}, +}; /// A vector clock index, this is associated with a thread id /// but in some cases one vector index may be shared with @@ -42,7 +47,37 @@ fn from(id: u32) -> Self { /// The type of the time-stamps recorded in the data-race detector /// set to a type of unsigned integer -pub type VTimestamp = u32; +#[derive(Clone, Copy, Debug, Eq)] +pub struct VTimestamp { + time: u32, + pub span: Span, +} + +impl VTimestamp { + pub const NONE: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP }; + + pub fn span_data(&self) -> SpanData { + self.span.data() + } +} + +impl PartialEq for VTimestamp { + fn eq(&self, other: &Self) -> bool { + self.time == other.time + } +} + +impl PartialOrd for VTimestamp { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for VTimestamp { + fn cmp(&self, other: &Self) -> Ordering { + self.time.cmp(&other.time) + } +} /// A vector clock for detecting data-races, this is conceptually /// a map from a vector index (and thus a thread id) to a timestamp. @@ -62,7 +97,7 @@ impl VClock { /// for a value at the given index pub fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock { let len = index.index() + 1; - let mut vec = smallvec::smallvec![0; len]; + let mut vec = smallvec::smallvec![VTimestamp::NONE; len]; vec[index.index()] = timestamp; VClock(vec) } @@ -79,7 +114,7 @@ pub fn as_slice(&self) -> &[VTimestamp] { #[inline] fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] { if self.0.len() < min_len { - self.0.resize(min_len, 0); + self.0.resize(min_len, VTimestamp::NONE); } assert!(self.0.len() >= min_len); self.0.as_mut_slice() @@ -88,11 +123,14 @@ fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] { /// Increment the vector clock at a known index /// this will panic if the vector index overflows #[inline] - pub fn increment_index(&mut self, idx: VectorIdx) { + pub fn increment_index(&mut self, idx: VectorIdx, current_span: Span) { let idx = idx.index(); let mut_slice = self.get_mut_with_min_len(idx + 1); let idx_ref = &mut mut_slice[idx]; - *idx_ref = idx_ref.checked_add(1).expect("Vector clock overflow") + idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow"); + if current_span != DUMMY_SP { + idx_ref.span = current_span; + } } // Join the two vector-clocks together, this @@ -102,14 +140,31 @@ pub fn join(&mut self, other: &Self) { let rhs_slice = other.as_slice(); let lhs_slice = self.get_mut_with_min_len(rhs_slice.len()); for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) { + let l_span = l.span; + let r_span = r.span; *l = r.max(*l); + if l.span == DUMMY_SP { + if r_span != DUMMY_SP { + l.span = r_span; + } + if l_span != DUMMY_SP { + l.span = l_span; + } + } } } /// Set the element at the current index of the vector pub fn set_at_index(&mut self, other: &Self, idx: VectorIdx) { let mut_slice = self.get_mut_with_min_len(idx.index() + 1); + + let prev_span = mut_slice[idx.index()].span; + mut_slice[idx.index()] = other[idx]; + + if other[idx].span == DUMMY_SP { + mut_slice[idx.index()].span = prev_span; + } } /// Set the vector to the all-zero vector @@ -313,7 +368,14 @@ impl Index for VClock { #[inline] fn index(&self, index: VectorIdx) -> &VTimestamp { - self.as_slice().get(index.to_u32() as usize).unwrap_or(&0) + self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::NONE) + } +} + +impl IndexMut for VClock { + #[inline] + fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp { + self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap() } } @@ -323,24 +385,25 @@ fn index(&self, index: VectorIdx) -> &VTimestamp { #[cfg(test)] mod tests { - use super::{VClock, VTimestamp, VectorIdx}; - use std::cmp::Ordering; + use super::{VClock, VectorIdx}; + use rustc_span::DUMMY_SP; #[test] fn test_equal() { let mut c1 = VClock::default(); let mut c2 = VClock::default(); assert_eq!(c1, c2); - c1.increment_index(VectorIdx(5)); + c1.increment_index(VectorIdx(5), DUMMY_SP); assert_ne!(c1, c2); - c2.increment_index(VectorIdx(53)); + c2.increment_index(VectorIdx(53), DUMMY_SP); assert_ne!(c1, c2); - c1.increment_index(VectorIdx(53)); + c1.increment_index(VectorIdx(53), DUMMY_SP); assert_ne!(c1, c2); - c2.increment_index(VectorIdx(5)); + c2.increment_index(VectorIdx(5), DUMMY_SP); assert_eq!(c1, c2); } + /* #[test] fn test_partial_order() { // Small test @@ -449,4 +512,5 @@ fn assert_order(l: &[VTimestamp], r: &[VTimestamp], o: Option) { "Invalid alt (>=):\n l: {l:?}\n r: {r:?}" ); } + */ } diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index 391681444d9..c02ec7ded75 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -258,7 +258,7 @@ fn new(init: Scalar) -> Self { // The thread index and timestamp of the initialisation write // are never meaningfully used, so it's fine to leave them as 0 store_index: VectorIdx::from(0), - timestamp: 0, + timestamp: VTimestamp::NONE, val: init, is_seqcst: false, load_info: RefCell::new(LoadInfo::default()), diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index efe79269b56..d9f40b55cd6 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -35,6 +35,17 @@ pub enum TerminationInfo { link_name: Symbol, span: SpanData, }, + DataRace { + op1: RacingOp, + op2: RacingOp, + ptr: Pointer, + }, +} + +pub struct RacingOp { + pub action: String, + pub thread_info: String, + pub span: SpanData, } impl fmt::Display for TerminationInfo { @@ -55,6 +66,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "multiple definitions of symbol `{link_name}`"), SymbolShimClashing { link_name, .. } => write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",), + DataRace { ptr, op1, op2 } => + write!( + f, + "Data race detected between {} on {} and {} on {} at {:?}", + op1.action, op1.thread_info, op2.action, op2.thread_info, ptr, + ), } } } @@ -167,7 +184,7 @@ pub fn report_error<'tcx, 'mir>( Abort(_) => Some("abnormal termination"), UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance => Some("unsupported operation"), - StackedBorrowsUb { .. } => Some("Undefined Behavior"), + StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"), Deadlock => Some("deadlock"), MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None, }; @@ -205,6 +222,13 @@ pub fn report_error<'tcx, 'mir>( vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))], Int2PtrWithStrictProvenance => vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))], + DataRace { ptr: _, op1, op2 } => + vec![ + (Some(op1.span), format!("The {} on {} is here", op1.action, op1.thread_info)), + (Some(op2.span), format!("The {} on {} is here", op2.action, op2.thread_info)), + (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")), + (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")), + ], _ => vec![], }; (title, helps) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index e5a748453e8..01a3d7550e2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -956,6 +956,7 @@ fn adjust_allocation<'b>( &ecx.machine.threads, alloc.size(), kind, + ecx.machine.current_span(), ) }); let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation); diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr index c6bfd12b241..d0ec8c1f128 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr +++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *pointer.load(Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `` and Allocate on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/alloc_read_race.rs:LL:CC + | +LL | ... *pointer.load(Ordering::Relaxed) + | ^ +help: The Allocate on thread `` is here + --> $DIR/alloc_read_race.rs:LL:CC + | +LL | pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr index c4efc175c20..11493536808 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *pointer.load(Ordering::Relaxed) = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `` and Allocate on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/alloc_write_race.rs:LL:CC + | +LL | ... *pointer.load(Ordering::Relaxed) = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Allocate on thread `` is here + --> $DIR/alloc_write_race.rs:LL:CC + | +LL | .store(Box::into_raw(Box::::new_uninit()) as *mut usize, Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr index 04adf0a98b6..e77afe7b827 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Load on thread `` and Write on thread `` at ALLOC | +help: The Atomic Load on thread `` is here + --> $DIR/atomic_read_na_write_race1.rs:LL:CC + | +LL | ... (&*c.0).load(Ordering::SeqCst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/atomic_read_na_write_race1.rs:LL:CC + | +LL | *(c.0 as *mut usize) = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr index b48f927b8fc..6b304421697 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *atomic_ref.get_mut() = 32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `` and Atomic Load on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/atomic_read_na_write_race2.rs:LL:CC + | +LL | ... *atomic_ref.get_mut() = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Atomic Load on thread `` is here + --> $DIR/atomic_read_na_write_race2.rs:LL:CC + | +LL | atomic_ref.load(Ordering::SeqCst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr index fdb9b353a67..32485d3f8f3 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *atomic_ref.get_mut() | ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `` and Atomic Store on thread `` at ALLOC | +help: The Read on thread `` is here + --> RUSTLIB/core/src/ptr/mod.rs:LL:CC + | +LL | } + | ^ +help: The Atomic Store on thread `` is here + --> $DIR/atomic_write_na_read_race1.rs:LL:CC + | +LL | atomic_ref.store(32, Ordering::SeqCst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr index ec581e322b7..5217f3d8a70 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Store on thread `` and Read on thread `` at ALLOC | +help: The Atomic Store on thread `` is here + --> $DIR/atomic_write_na_read_race2.rs:LL:CC + | +LL | ... (&*c.0).store(32, Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Read on thread `` is here + --> RUSTLIB/core/src/ptr/mod.rs:LL:CC + | +LL | } + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr index 4c75f94d71c..55cc212ec0a 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Store on thread `` and Write on thread `` at ALLOC | +help: The Atomic Store on thread `` is here + --> $DIR/atomic_write_na_write_race1.rs:LL:CC + | +LL | ... (&*c.0).store(64, Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/atomic_write_na_write_race1.rs:LL:CC + | +LL | *(c.0 as *mut usize) = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr index 8c7f14081c8..2b666ef0276 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *atomic_ref.get_mut() = 32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `` and Atomic Store on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/atomic_write_na_write_race2.rs:LL:CC + | +LL | ... *atomic_ref.get_mut() = 32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Atomic Store on thread `` is here + --> $DIR/atomic_write_na_write_race2.rs:LL:CC + | +LL | atomic_ref.store(64, Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr index 663bb8d4af5..156261b3538 100644 --- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr +++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *c.0 = 64; | ^^^^^^^^^ Data race detected between Write on thread `` and Write on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/dangling_thread_async_race.rs:LL:CC + | +LL | *c.0 = 64; + | ^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/dangling_thread_async_race.rs:LL:CC + | +LL | *c.0 = 32; + | ^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr index ad3e1735378..bd0d34929e7 100644 --- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr +++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `main` and LL | *c.0 = 64; | ^^^^^^^^^ Data race detected between Write on thread `main` and Write on thread `` at ALLOC | +help: The Write on thread `main` is here + --> $DIR/dangling_thread_race.rs:LL:CC + | +LL | *c.0 = 64; + | ^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/dangling_thread_race.rs:LL:CC + | +LL | *c.0 = 32; + | ^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr index 194c2260baa..ac20d05bf12 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr @@ -9,6 +9,21 @@ LL | | std::mem::align_of::(), LL | | ); | |_____________^ Data race detected between Deallocate on thread `` and Read on thread `` at ALLOC | +help: The Deallocate on thread `` is here + --> $DIR/dealloc_read_race1.rs:LL:CC + | +LL | / __rust_dealloc( +LL | | +LL | | ptr.0 as *mut _, +LL | | std::mem::size_of::(), +LL | | std::mem::align_of::(), +LL | | ); + | |_____________^ +help: The Read on thread `` is here + --> RUSTLIB/core/src/ptr/mod.rs:LL:CC + | +LL | } + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr index c986e912f03..93c7db38751 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Deallocate on thread `` and Read on thread `` at ALLOC | +help: The Deallocate on thread `` is here + --> $DIR/dealloc_read_race_stack.rs:LL:CC + | +LL | } + | ^ +help: The Read on thread `` is here + --> $DIR/dealloc_read_race_stack.rs:LL:CC + | +LL | *pointer.load(Ordering::Acquire) + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr index 56eb0b519c4..9e59d5a6478 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr @@ -9,6 +9,21 @@ LL | | std::mem::align_of::(), LL | | ); | |_____________^ Data race detected between Deallocate on thread `` and Write on thread `` at ALLOC | +help: The Deallocate on thread `` is here + --> $DIR/dealloc_write_race1.rs:LL:CC + | +LL | / __rust_dealloc( +LL | | +LL | | ptr.0 as *mut _, +LL | | std::mem::size_of::(), +LL | | std::mem::align_of::(), +LL | | ); + | |_____________^ +help: The Write on thread `` is here + --> $DIR/dealloc_write_race1.rs:LL:CC + | +LL | *ptr.0 = 2; + | ^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr index 7b77e2470a1..5ac7c2d5a1e 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Deallocate on thread `` and Write on thread `` at ALLOC | +help: The Deallocate on thread `` is here + --> $DIR/dealloc_write_race_stack.rs:LL:CC + | +LL | } + | ^ +help: The Write on thread `` is here + --> $DIR/dealloc_write_race_stack.rs:LL:CC + | +LL | *pointer.load(Ordering::Acquire) = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr index 26c07ae6962..636a686f84e 100644 --- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr +++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *c.0 = 64; | ^^^^^^^^^ Data race detected between Write on thread `` and Write on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/enable_after_join_to_main.rs:LL:CC + | +LL | *c.0 = 64; + | ^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/enable_after_join_to_main.rs:LL:CC + | +LL | *c.0 = 32; + | ^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr index 0abfe213db1..e6862916384 100644 --- a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr +++ b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `main` and LL | unsafe { V = 2 } | ^^^^^ Data race detected between Write on thread `main` and Write on thread `` at ALLOC | +help: The Write on thread `main` is here + --> $DIR/fence_after_load.rs:LL:CC + | +LL | unsafe { V = 2 } + | ^^^^^ +help: The Write on thread `` is here + --> $DIR/fence_after_load.rs:LL:CC + | +LL | unsafe { V = 1 } + | ^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.stderr b/src/tools/miri/tests/fail/data_race/read_write_race.stderr index 08a19537312..b1441dabaf0 100644 --- a/src/tools/miri/tests/fail/data_race/read_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/read_write_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *c.0 = 64; | ^^^^^^^^^ Data race detected between Write on thread `` and Read on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/read_write_race.rs:LL:CC + | +LL | *c.0 = 64; + | ^^^^^^^^^ +help: The Read on thread `` is here + --> RUSTLIB/core/src/ptr/mod.rs:LL:CC + | +LL | } + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr index 20f137afe73..2a2572576db 100644 --- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | stack_var | ^^^^^^^^^ Data race detected between Read on thread `` and Write on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/read_write_race_stack.rs:LL:CC + | +LL | sleep(Duration::from_millis(200)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/read_write_race_stack.rs:LL:CC + | +LL | *pointer.load(Ordering::Acquire) = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr index 6121c25db22..e4819614ddb 100644 --- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr +++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *c.0 | ^^^^ Data race detected between Read on thread `` and Write on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/relax_acquire_race.rs:LL:CC + | +LL | if SYNC.load(Ordering::Acquire) == 2 { + | ^ +help: The Write on thread `` is here + --> $DIR/relax_acquire_race.rs:LL:CC + | +LL | *c.0 = 1; + | ^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr index 777bc4adadc..6bc8bccbbf0 100644 --- a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr +++ b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *c.0 | ^^^^ Data race detected between Read on thread `` and Write on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/release_seq_race.rs:LL:CC + | +LL | if SYNC.load(Ordering::Acquire) == 3 { + | ^ +help: The Write on thread `` is here + --> $DIR/release_seq_race.rs:LL:CC + | +LL | *c.0 = 1; + | ^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr index 0fcb192d920..6997685dc3e 100644 --- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr +++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *c.0 | ^^^^ Data race detected between Read on thread `` and Write on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/release_seq_race_same_thread.rs:LL:CC + | +LL | if SYNC.load(Ordering::Acquire) == 2 { + | ^ +help: The Write on thread `` is here + --> $DIR/release_seq_race_same_thread.rs:LL:CC + | +LL | *c.0 = 1; + | ^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.stderr b/src/tools/miri/tests/fail/data_race/rmw_race.stderr index 3ae6f3b84fe..e4f3ecf89ce 100644 --- a/src/tools/miri/tests/fail/data_race/rmw_race.stderr +++ b/src/tools/miri/tests/fail/data_race/rmw_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `` LL | *c.0 | ^^^^ Data race detected between Read on thread `` and Write on thread `` at ALLOC | +help: The Read on thread `` is here + --> $DIR/rmw_race.rs:LL:CC + | +LL | if SYNC.load(Ordering::Acquire) == 3 { + | ^ +help: The Write on thread `` is here + --> $DIR/rmw_race.rs:LL:CC + | +LL | *c.0 = 1; + | ^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr index 0075f877b29..b156179da4d 100644 --- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr +++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Deallocate on thread `main LL | } | ^ Data race detected between Deallocate on thread `main` and Read on thread `` at ALLOC | +help: The Deallocate on thread `main` is here + --> $DIR/stack_pop_race.rs:LL:CC + | +LL | } + | ^ +help: The Read on thread `` is here + --> RUSTLIB/core/src/ptr/mod.rs:LL:CC + | +LL | } + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.stderr b/src/tools/miri/tests/fail/data_race/write_write_race.stderr index ee7072ccf5d..132cd503044 100644 --- a/src/tools/miri/tests/fail/data_race/write_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/write_write_race.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *c.0 = 64; | ^^^^^^^^^ Data race detected between Write on thread `` and Write on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/write_write_race.rs:LL:CC + | +LL | *c.0 = 64; + | ^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/write_write_race.rs:LL:CC + | +LL | *c.0 = 32; + | ^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr index ceb473c2a4a..25963d63db5 100644 --- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | stack_var = 1usize; | ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `` and Write on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/write_write_race_stack.rs:LL:CC + | +LL | stack_var = 1usize; + | ^^^^^^^^^^^^^^^^^^ +help: The Write on thread `` is here + --> $DIR/write_write_race_stack.rs:LL:CC + | +LL | *pointer.load(Ordering::Acquire) = 3; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr index 5dc936f0707..6b280a16a37 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *p = 5; | ^^^^^^ Data race detected between Write on thread `` and Read on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/retag_data_race_read.rs:LL:CC + | +LL | *p = 5; + | ^^^^^^ +help: The Read on thread `` is here + --> $DIR/retag_data_race_read.rs:LL:CC + | +LL | let t1 = std::thread::spawn(move || thread_1(p)); + | ^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr index 03c24503564..80b6ac6e139 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr @@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread ` LL | *p = 5; | ^^^^^^ Data race detected between Write on thread `` and Write on thread `` at ALLOC | +help: The Write on thread `` is here + --> $DIR/retag_data_race_write.rs:LL:CC + | +LL | *p = 5; + | ^^^^^^ +help: The Write on thread `` is here + --> $DIR/retag_data_race_write.rs:LL:CC + | +LL | let _r = &mut *p; + | ^^^^^^^ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: