Skip to content

Commit

Permalink
Auto merge of #2548 - RalfJung:remove-tls-diagnostics-hack, r=RalfJung
Browse files Browse the repository at this point in the history
avoid thread-local var indirection for non-halting diagnostics

This hack used to be necessary because Stacked Borrows did not have access to enough parts of the machine. But that got fixed a while ago, so now we can just emit diagnostics directly, which is a lot more reliable.

Needs rust-lang/rust#101985
Fixes #2538
  • Loading branch information
bors committed Sep 20, 2022
2 parents 4b9463c + 7687b7e commit d9ad25e
Show file tree
Hide file tree
Showing 47 changed files with 362 additions and 410 deletions.
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2019147c5642c08cdb9ad4cacd97dd1fa4ffa701
acb8934fd57b3c2740c4abac0a5728c2c9b1423b
12 changes: 6 additions & 6 deletions src/concurrency/data_race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,8 @@ impl MemoryCellClocks {
}

/// Evaluation context extensions.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
/// Atomic variant of read_scalar_at_offset.
fn read_scalar_at_offset_atomic(
&self,
Expand Down Expand Up @@ -940,8 +940,8 @@ impl VClockAlloc {
}
}

impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {}
trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
/// Temporarily allow data-races to occur. This should only be used in
/// one of these cases:
/// - One of the appropriate `validate_atomic` functions will be called to
Expand All @@ -950,7 +950,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
/// cannot be accessed by the interpreted program.
/// - Execution of the interpreted program execution has halted.
#[inline]
fn allow_data_races_ref<R>(&self, op: impl FnOnce(&MiriEvalContext<'mir, 'tcx>) -> R) -> R {
fn allow_data_races_ref<R>(&self, op: impl FnOnce(&MiriInterpCx<'mir, 'tcx>) -> R) -> R {
let this = self.eval_context_ref();
if let Some(data_race) = &this.machine.data_race {
let old = data_race.ongoing_action_data_race_free.replace(true);
Expand All @@ -969,7 +969,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
#[inline]
fn allow_data_races_mut<R>(
&mut self,
op: impl FnOnce(&mut MiriEvalContext<'mir, 'tcx>) -> R,
op: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> R,
) -> R {
let this = self.eval_context_mut();
if let Some(data_race) = &this.machine.data_race {
Expand Down
17 changes: 7 additions & 10 deletions src/concurrency/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ pub(crate) struct SynchronizationState {
}

// Private extension trait for local helper methods
impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Take a reader out of the queue waiting for the lock.
/// Returns `true` if some thread got the rwlock.
#[inline]
Expand Down Expand Up @@ -208,8 +208,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// cases, the function calls are infallible and it is the client's (shim
// implementation's) responsibility to detect and deal with erroneous
// situations.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
#[inline]
/// Create state for a new mutex.
fn mutex_create(&mut self) -> MutexId {
Expand All @@ -222,7 +222,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
/// otherwise returns the value from the closure
fn mutex_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, MutexId>
where
F: FnOnce(&mut MiriEvalContext<'mir, 'tcx>, MutexId) -> InterpResult<'tcx, Option<MutexId>>,
F: FnOnce(&mut MiriInterpCx<'mir, 'tcx>, MutexId) -> InterpResult<'tcx, Option<MutexId>>,
{
let this = self.eval_context_mut();
let next_index = this.machine.threads.sync.mutexes.next_index();
Expand Down Expand Up @@ -322,10 +322,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
/// otherwise returns the value from the closure
fn rwlock_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, RwLockId>
where
F: FnOnce(
&mut MiriEvalContext<'mir, 'tcx>,
RwLockId,
) -> InterpResult<'tcx, Option<RwLockId>>,
F: FnOnce(&mut MiriInterpCx<'mir, 'tcx>, RwLockId) -> InterpResult<'tcx, Option<RwLockId>>,
{
let this = self.eval_context_mut();
let next_index = this.machine.threads.sync.rwlocks.next_index();
Expand Down Expand Up @@ -492,7 +489,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
fn condvar_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, CondvarId>
where
F: FnOnce(
&mut MiriEvalContext<'mir, 'tcx>,
&mut MiriInterpCx<'mir, 'tcx>,
CondvarId,
) -> InterpResult<'tcx, Option<CondvarId>>,
{
Expand Down
11 changes: 6 additions & 5 deletions src/concurrency/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ pub enum SchedulingAction {

/// Timeout callbacks can be created by synchronization primitives to tell the
/// scheduler that they should be called once some period of time passes.
type TimeoutCallback<'mir, 'tcx> =
Box<dyn FnOnce(&mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx>;
type TimeoutCallback<'mir, 'tcx> = Box<
dyn FnOnce(&mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx,
>;

/// A thread identifier.
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -253,7 +254,7 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
}

impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
pub(crate) fn init(ecx: &mut MiriEvalContext<'mir, 'tcx>) {
pub(crate) fn init(ecx: &mut MiriInterpCx<'mir, 'tcx>) {
if ecx.tcx.sess.target.os.as_ref() != "windows" {
// The main thread can *not* be joined on except on windows.
ecx.machine.threads.threads[ThreadId::new(0)].join_status = ThreadJoinStatus::Detached;
Expand Down Expand Up @@ -628,8 +629,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
}

// Public interface to thread management.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Get a thread-specific allocation id for the given thread-local static.
/// If needed, allocate a new one.
fn get_or_create_thread_local_alloc(
Expand Down
10 changes: 5 additions & 5 deletions src/concurrency/weak_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,9 @@ impl StoreElement {
}
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
crate::MiriEvalContextExt<'mir, 'tcx>
crate::MiriInterpCxExt<'mir, 'tcx>
{
// If weak memory emulation is enabled, check if this atomic op imperfectly overlaps with a previous
// atomic read or write. If it does, then we require it to be ordered (non-racy) with all previous atomic
Expand Down Expand Up @@ -502,7 +502,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
if let (
crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
crate::Evaluator { data_race: Some(global), threads, .. },
crate::MiriMachine { data_race: Some(global), threads, .. },
) = this.get_alloc_extra_mut(alloc_id)?
{
if atomic == AtomicRwOrd::SeqCst {
Expand Down Expand Up @@ -544,7 +544,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
validate,
)?;
if global.track_outdated_loads && recency == LoadRecency::Outdated {
register_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad);
this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad);
}

return Ok(loaded);
Expand All @@ -567,7 +567,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr)?;
if let (
crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
crate::Evaluator { data_race: Some(global), threads, .. },
crate::MiriMachine { data_race: Some(global), threads, .. },
) = this.get_alloc_extra_mut(alloc_id)?
{
if atomic == AtomicWriteOrd::SeqCst {
Expand Down
Loading

0 comments on commit d9ad25e

Please sign in to comment.