stop using process-wide state, now that we are running multiple interpreters in the same thread

This commit is contained in:
Ralf Jung 2024-12-23 12:44:54 +01:00
parent d04b972f72
commit 0f49f0ffdf
6 changed files with 47 additions and 47 deletions

View file

@ -9,7 +9,6 @@ use std::cmp::max;
use rand::Rng;
use rustc_abi::{Align, Size};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_span::Span;
use self::reuse_pool::ReusePool;
use crate::concurrency::VClock;
@ -319,17 +318,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
match global_state.provenance_mode {
ProvenanceMode::Default => {
// The first time this happens at a particular location, print a warning.
thread_local! {
// `Span` is non-`Send`, so we use a thread-local instead.
static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
let mut int2ptr_warned = this.machine.int2ptr_warned.borrow_mut();
let first = int2ptr_warned.is_empty();
if int2ptr_warned.insert(this.cur_span()) {
// Newly inserted, so first time we see this span.
this.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
}
PAST_WARNINGS.with_borrow_mut(|past_warnings| {
let first = past_warnings.is_empty();
if past_warnings.insert(this.cur_span()) {
// Newly inserted, so first time we see this span.
this.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
}
});
}
ProvenanceMode::Strict => {
throw_machine_stop!(TerminationInfo::Int2PtrWithStrictProvenance);

View file

@ -5,7 +5,6 @@ pub mod diagnostics;
mod item;
mod stack;
use std::cell::RefCell;
use std::fmt::Write;
use std::{cmp, mem};
@ -822,16 +821,9 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
let size = match size {
Some(size) => size,
None => {
// The first time this happens, show a warning.
thread_local! { static WARNING_SHOWN: RefCell<bool> = const { RefCell::new(false) }; }
WARNING_SHOWN.with_borrow_mut(|shown| {
if *shown {
return;
}
// Not yet shown. Show it!
*shown = true;
if !this.machine.sb_extern_type_warned.replace(true) {
this.emit_diagnostic(NonHaltingDiagnostic::ExternTypeReborrow);
});
}
return interp_ok(place.clone());
}
};

View file

@ -1,6 +1,4 @@
use std::collections::BTreeSet;
use std::num::NonZero;
use std::sync::Mutex;
use std::time::Duration;
use std::{cmp, iter};
@ -641,11 +639,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
match reject_with {
RejectOpWith::Abort => isolation_abort_error(op_name),
RejectOpWith::WarningWithoutBacktrace => {
// This exists to reduce verbosity; make sure we emit the warning at most once per
// operation.
static EMITTED_WARNINGS: Mutex<BTreeSet<String>> = Mutex::new(BTreeSet::new());
let mut emitted_warnings = EMITTED_WARNINGS.lock().unwrap();
let mut emitted_warnings = this.machine.reject_in_isolation_warned.borrow_mut();
if !emitted_warnings.contains(op_name) {
// First time we are seeing this.
emitted_warnings.insert(op_name.to_owned());
@ -653,6 +647,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
.dcx()
.warn(format!("{op_name} was made to return an error due to isolation"));
}
interp_ok(())
}
RejectOpWith::Warning => {

View file

@ -3,7 +3,7 @@
use std::any::Any;
use std::borrow::Cow;
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry;
use std::path::Path;
use std::{fmt, process};
@ -595,6 +595,21 @@ pub struct MiriMachine<'tcx> {
/// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
/// Caches the sanity-checks for various pthread primitives.
pub(crate) pthread_mutex_sanity: Cell<bool>,
pub(crate) pthread_rwlock_sanity: Cell<bool>,
pub(crate) pthread_condvar_sanity: Cell<bool>,
/// Remembers whether we already warned about an extern type with Stacked Borrows.
pub(crate) sb_extern_type_warned: Cell<bool>,
/// Remember whether we already warned about sharing memory with a native call.
#[cfg(unix)]
pub(crate) native_call_mem_warned: Cell<bool>,
/// Remembers which shims have already shown the warning about erroring in isolation.
pub(crate) reject_in_isolation_warned: RefCell<FxHashSet<String>>,
/// Remembers which int2ptr casts we have already warned about.
pub(crate) int2ptr_warned: RefCell<FxHashSet<Span>>,
}
impl<'tcx> MiriMachine<'tcx> {
@ -732,6 +747,14 @@ impl<'tcx> MiriMachine<'tcx> {
const_cache: RefCell::new(FxHashMap::default()),
symbolic_alignment: RefCell::new(FxHashMap::default()),
union_data_ranges: FxHashMap::default(),
pthread_mutex_sanity: Cell::new(false),
pthread_rwlock_sanity: Cell::new(false),
pthread_condvar_sanity: Cell::new(false),
sb_extern_type_warned: Cell::new(false),
#[cfg(unix)]
native_call_mem_warned: Cell::new(false),
reject_in_isolation_warned: Default::default(),
int2ptr_warned: Default::default(),
}
}
@ -844,6 +867,14 @@ impl VisitProvenance for MiriMachine<'_> {
const_cache: _,
symbolic_alignment: _,
union_data_ranges: _,
pthread_mutex_sanity: _,
pthread_rwlock_sanity: _,
pthread_condvar_sanity: _,
sb_extern_type_warned: _,
#[cfg(unix)]
native_call_mem_warned: _,
reject_in_isolation_warned: _,
int2ptr_warned: _,
} = self;
threads.visit_provenance(visit);

View file

@ -1,5 +1,4 @@
//! Implements calling functions from a native library.
use std::cell::RefCell;
use std::ops::Deref;
use libffi::high::call as ffi;
@ -174,16 +173,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
continue;
};
// The first time this happens, print a warning.
thread_local! {
static HAVE_WARNED: RefCell<bool> = const { RefCell::new(false) };
if !this.machine.native_call_mem_warned.replace(true) {
// Newly set, so first time we get here.
this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem);
}
HAVE_WARNED.with_borrow_mut(|have_warned| {
if !*have_warned {
// Newly inserted, so first time we see this span.
this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem);
*have_warned = true;
}
});
this.prepare_for_native_call(alloc_id, prov)?;
}

View file

@ -1,5 +1,3 @@
use std::sync::atomic::{AtomicBool, Ordering};
use rustc_abi::Size;
use crate::concurrency::sync::LAZY_INIT_COOKIE;
@ -136,8 +134,7 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size>
// Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
// the `init` field must start out not equal to INIT_COOKIE.
static SANITY: AtomicBool = AtomicBool::new(false);
if !SANITY.swap(true, Ordering::Relaxed) {
if !ecx.machine.pthread_mutex_sanity.replace(true) {
let check_static_initializer = |name| {
let static_initializer = ecx.eval_path(&["libc", name]);
let init_field =
@ -248,8 +245,7 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size
// Sanity-check this against PTHREAD_RWLOCK_INITIALIZER (but only once):
// the `init` field must start out not equal to LAZY_INIT_COOKIE.
static SANITY: AtomicBool = AtomicBool::new(false);
if !SANITY.swap(true, Ordering::Relaxed) {
if !ecx.machine.pthread_rwlock_sanity.replace(true) {
let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]);
let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap();
let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap();
@ -357,8 +353,7 @@ fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size>
// Sanity-check this against PTHREAD_COND_INITIALIZER (but only once):
// the `init` field must start out not equal to LAZY_INIT_COOKIE.
static SANITY: AtomicBool = AtomicBool::new(false);
if !SANITY.swap(true, Ordering::Relaxed) {
if !ecx.machine.pthread_condvar_sanity.replace(true) {
let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]);
let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap();
let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap();