Auto merge of #115220 - Zoxc:revive-gcx-ptr, r=oli-obk
Add a `CurrentGcx` type to let the deadlock handler access `TyCtxt` This brings back `GCX_PTR` (previously removed in https://github.com/rust-lang/rust/pull/74969) allowing the deadlock handler access to `GlobalCtxt`. This fixes https://github.com/rust-lang/rust/issues/111522. r? `@cjgillot`
This commit is contained in:
commit
c5e7f45b62
5 changed files with 88 additions and 16 deletions
|
@ -32,6 +32,7 @@ use crate::ty::{
|
|||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
use rustc_ast::{self as ast, attr};
|
||||
use rustc_data_structures::defer;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
|
@ -39,7 +40,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
|
|||
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal};
|
||||
use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, RwLock, WorkerLocal};
|
||||
#[cfg(parallel_compiler)]
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
|
@ -723,6 +724,8 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
/// Stores memory for globals (statics/consts).
|
||||
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
||||
|
||||
current_gcx: CurrentGcx,
|
||||
}
|
||||
|
||||
impl<'tcx> GlobalCtxt<'tcx> {
|
||||
|
@ -733,6 +736,19 @@ impl<'tcx> GlobalCtxt<'tcx> {
|
|||
F: FnOnce(TyCtxt<'tcx>) -> R,
|
||||
{
|
||||
let icx = tls::ImplicitCtxt::new(self);
|
||||
|
||||
// Reset `current_gcx` to `None` when we exit.
|
||||
let _on_drop = defer(move || {
|
||||
*self.current_gcx.value.write() = None;
|
||||
});
|
||||
|
||||
// Set this `GlobalCtxt` as the current one.
|
||||
{
|
||||
let mut guard = self.current_gcx.value.write();
|
||||
assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
|
||||
*guard = Some(self as *const _ as *const ());
|
||||
}
|
||||
|
||||
tls::enter_context(&icx, || f(icx.tcx))
|
||||
}
|
||||
|
||||
|
@ -741,6 +757,39 @@ impl<'tcx> GlobalCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is used to get a reference to a `GlobalCtxt` if one is available.
|
||||
///
|
||||
/// This is needed to allow the deadlock handler access to `GlobalCtxt` to look for query cycles.
|
||||
/// It cannot use the `TLV` global because that's only guaranteed to be defined on the thread
|
||||
/// creating the `GlobalCtxt`. Other threads have access to the `TLV` only inside Rayon jobs, but
|
||||
/// the deadlock handler is not called inside such a job.
|
||||
#[derive(Clone)]
|
||||
pub struct CurrentGcx {
|
||||
/// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter`
|
||||
/// and reset to `None` when that function returns or unwinds.
|
||||
value: Lrc<RwLock<Option<*const ()>>>,
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl DynSend for CurrentGcx {}
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl DynSync for CurrentGcx {}
|
||||
|
||||
impl CurrentGcx {
|
||||
pub fn new() -> Self {
|
||||
Self { value: Lrc::new(RwLock::new(None)) }
|
||||
}
|
||||
|
||||
pub fn access<R>(&self, f: impl for<'tcx> FnOnce(&'tcx GlobalCtxt<'tcx>) -> R) -> R {
|
||||
let read_guard = self.value.read();
|
||||
let gcx: *const GlobalCtxt<'_> = read_guard.unwrap() as *const _;
|
||||
// SAFETY: We hold the read lock for the `GlobalCtxt` pointer. That prevents
|
||||
// `GlobalCtxt::enter` from returning as it would first acquire the write lock.
|
||||
// This ensures the `GlobalCtxt` is live during `f`.
|
||||
f(unsafe { &*gcx })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Expects a body and returns its codegen attributes.
|
||||
///
|
||||
|
@ -859,6 +908,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
query_kinds: &'tcx [DepKindStruct<'tcx>],
|
||||
query_system: QuerySystem<'tcx>,
|
||||
hooks: crate::hooks::Providers,
|
||||
current_gcx: CurrentGcx,
|
||||
) -> GlobalCtxt<'tcx> {
|
||||
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
||||
s.dcx().emit_fatal(err);
|
||||
|
@ -893,6 +943,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
canonical_param_env_cache: Default::default(),
|
||||
data_layout,
|
||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||
current_gcx,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ pub use self::consts::{
|
|||
Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
TyCtxtFeed,
|
||||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||
TyCtxt, TyCtxtFeed,
|
||||
};
|
||||
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
|
||||
pub use self::list::List;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue