Include a Span in VClock

This commit is contained in:
Ben Kimock 2022-10-30 21:04:00 -04:00
parent e82a604a88
commit d1184ae58d
35 changed files with 531 additions and 88 deletions

View File

@ -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<MiriMemoryKind>,
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<VectorIdx> {
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<A: Debug + Copy>(
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<A: Debug + Copy>(
// 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<VectorIdx> {
// 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

View File

@ -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.

View File

@ -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<usize> {
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<usiz
// The mutex is completely unlocked. Try transfering ownership
// to another thread.
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release(&mut mutex.data_race, current_owner);
data_race.validate_lock_release(
&mut mutex.data_race,
current_owner,
current_span,
);
}
this.mutex_dequeue_and_lock(id);
}
@ -454,6 +459,7 @@ fn rwlock_reader_lock(&mut self, id: RwLockId, reader: ThreadId) {
/// Returns `true` if succeeded, `false` if this `reader` did not hold the lock.
fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> 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<ThreadId> {
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.

View File

@ -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<Pointer<Provenance>> {
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(())

View File

@ -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<Ordering> {
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<VectorIdx> 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<VectorIdx> 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<Ordering>) {
"Invalid alt (>=):\n l: {l:?}\n r: {r:?}"
);
}
*/
}

View File

@ -258,7 +258,7 @@ fn new(init: Scalar<Provenance>) -> 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()),

View File

@ -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)

View File

@ -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);

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *pointer.load(Ordering::Relaxed)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/alloc_read_race.rs:LL:CC
|
LL | ... *pointer.load(Ordering::Relaxed)
| ^
help: The Allocate on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *pointer.load(Ordering::Relaxed) = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/alloc_write_race.rs:LL:CC
|
LL | ... *pointer.load(Ordering::Relaxed) = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Allocate on thread `<unnamed>` is here
--> $DIR/alloc_write_race.rs:LL:CC
|
LL | .store(Box::into_raw(Box::<usize>::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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Load on thread `<un
LL | (&*c.0).load(Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Atomic Load on thread `<unnamed>` is here
--> $DIR/atomic_read_na_write_race1.rs:LL:CC
|
LL | ... (&*c.0).load(Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/atomic_read_na_write_race2.rs:LL:CC
|
LL | ... *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Atomic Load on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *atomic_ref.get_mut()
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
LL | }
| ^
help: The Atomic Store on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Store on thread `<u
LL | (&*c.0).store(32, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
help: The Atomic Store on thread `<unnamed>` is here
--> $DIR/atomic_write_na_read_race2.rs:LL:CC
|
LL | ... (&*c.0).store(32, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Read on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Atomic Store on thread `<u
LL | (&*c.0).store(64, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Atomic Store on thread `<unnamed>` is here
--> $DIR/atomic_write_na_write_race1.rs:LL:CC
|
LL | ... (&*c.0).store(64, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/atomic_write_na_write_race2.rs:LL:CC
|
LL | ... *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Atomic Store on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/dangling_thread_async_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -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 `<unnamed>` 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 `<unnamed>` 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:

View File

@ -9,6 +9,21 @@ LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
help: The Deallocate on thread `<unnamed>` is here
--> $DIR/dealloc_read_race1.rs:LL:CC
|
LL | / __rust_dealloc(
LL | |
LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^
help: The Read on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Deallocate on thread `<unn
LL | }
| ^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
help: The Deallocate on thread `<unnamed>` is here
--> $DIR/dealloc_read_race_stack.rs:LL:CC
|
LL | }
| ^
help: The Read on thread `<unnamed>` 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:

View File

@ -9,6 +9,21 @@ LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Deallocate on thread `<unnamed>` is here
--> $DIR/dealloc_write_race1.rs:LL:CC
|
LL | / __rust_dealloc(
LL | |
LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Deallocate on thread `<unn
LL | }
| ^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Deallocate on thread `<unnamed>` is here
--> $DIR/dealloc_write_race_stack.rs:LL:CC
|
LL | }
| ^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/enable_after_join_to_main.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -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 `<unnamed>` 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 `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/read_write_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^
help: The Read on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | stack_var
| ^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/read_write_race_stack.rs:LL:CC
|
LL | sleep(Duration::from_millis(200));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/relax_acquire_race.rs:LL:CC
|
LL | if SYNC.load(Ordering::Acquire) == 2 {
| ^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/release_seq_race.rs:LL:CC
|
LL | if SYNC.load(Ordering::Acquire) == 3 {
| ^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/release_seq_race_same_thread.rs:LL:CC
|
LL | if SYNC.load(Ordering::Acquire) == 2 {
| ^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Read on thread `<unnamed>`
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Read on thread `<unnamed>` is here
--> $DIR/rmw_race.rs:LL:CC
|
LL | if SYNC.load(Ordering::Acquire) == 3 {
| ^
help: The Write on thread `<unnamed>` 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:

View File

@ -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 `<unnamed>` at ALLOC
|
help: The Deallocate on thread `main` is here
--> $DIR/stack_pop_race.rs:LL:CC
|
LL | }
| ^
help: The Read on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/write_write_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | stack_var = 1usize;
| ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/write_write_race_stack.rs:LL:CC
|
LL | stack_var = 1usize;
| ^^^^^^^^^^^^^^^^^^
help: The Write on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *p = 5;
| ^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/retag_data_race_read.rs:LL:CC
|
LL | *p = 5;
| ^^^^^^
help: The Read on thread `<unnamed>` 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:

View File

@ -4,6 +4,16 @@ error: Undefined Behavior: Data race detected between Write on thread `<unnamed>
LL | *p = 5;
| ^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
help: The Write on thread `<unnamed>` is here
--> $DIR/retag_data_race_write.rs:LL:CC
|
LL | *p = 5;
| ^^^^^^
help: The Write on thread `<unnamed>` 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: