@@ -32,14 +32,15 @@ use crate::ty::{
32
32
} ;
33
33
use crate :: ty:: { GenericArg , GenericArgs , GenericArgsRef } ;
34
34
use rustc_ast:: { self as ast, attr} ;
35
+ use rustc_data_structures:: defer;
35
36
use rustc_data_structures:: fingerprint:: Fingerprint ;
36
37
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
37
38
use rustc_data_structures:: intern:: Interned ;
38
39
use rustc_data_structures:: profiling:: SelfProfilerRef ;
39
40
use rustc_data_structures:: sharded:: { IntoPointer , ShardedHashMap } ;
40
41
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
41
42
use rustc_data_structures:: steal:: Steal ;
42
- use rustc_data_structures:: sync:: { self , FreezeReadGuard , Lock , Lrc , WorkerLocal } ;
43
+ use rustc_data_structures:: sync:: { self , FreezeReadGuard , Lock , Lrc , RwLock , WorkerLocal } ;
43
44
#[ cfg( parallel_compiler) ]
44
45
use rustc_data_structures:: sync:: { DynSend , DynSync } ;
45
46
use rustc_data_structures:: unord:: UnordSet ;
@@ -723,6 +724,8 @@ pub struct GlobalCtxt<'tcx> {
723
724
724
725
/// Stores memory for globals (statics/consts).
725
726
pub ( crate ) alloc_map : Lock < interpret:: AllocMap < ' tcx > > ,
727
+
728
+ current_gcx : CurrentGcx ,
726
729
}
727
730
728
731
impl < ' tcx > GlobalCtxt < ' tcx > {
@@ -733,6 +736,19 @@ impl<'tcx> GlobalCtxt<'tcx> {
733
736
F : FnOnce ( TyCtxt < ' tcx > ) -> R ,
734
737
{
735
738
let icx = tls:: ImplicitCtxt :: new ( self ) ;
739
+
740
+ // Reset `current_gcx` to `None` when we exit.
741
+ let _on_drop = defer ( move || {
742
+ * self . current_gcx . value . write ( ) = None ;
743
+ } ) ;
744
+
745
+ // Set this `GlobalCtxt` as the current one.
746
+ {
747
+ let mut guard = self . current_gcx . value . write ( ) ;
748
+ assert ! ( guard. is_none( ) , "no `GlobalCtxt` is currently set" ) ;
749
+ * guard = Some ( self as * const _ as * const ( ) ) ;
750
+ }
751
+
736
752
tls:: enter_context ( & icx, || f ( icx. tcx ) )
737
753
}
738
754
@@ -741,6 +757,39 @@ impl<'tcx> GlobalCtxt<'tcx> {
741
757
}
742
758
}
743
759
760
+ /// This is used to get a reference to a `GlobalCtxt` if one is available.
761
+ ///
762
+ /// This is needed to allow the deadlock handler access to `GlobalCtxt` to look for query cycles.
763
+ /// It cannot use the `TLV` global because that's only guaranteed to be defined on the thread
764
+ /// creating the `GlobalCtxt`. Other threads have access to the `TLV` only inside Rayon jobs, but
765
+ /// the deadlock handler is not called inside such a job.
766
+ #[ derive( Clone ) ]
767
+ pub struct CurrentGcx {
768
+ /// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter`
769
+ /// and reset to `None` when that function returns or unwinds.
770
+ value : Lrc < RwLock < Option < * const ( ) > > > ,
771
+ }
772
+
773
+ #[ cfg( parallel_compiler) ]
774
+ unsafe impl DynSend for CurrentGcx { }
775
+ #[ cfg( parallel_compiler) ]
776
+ unsafe impl DynSync for CurrentGcx { }
777
+
778
+ impl CurrentGcx {
779
+ pub fn new ( ) -> Self {
780
+ Self { value : Lrc :: new ( RwLock :: new ( None ) ) }
781
+ }
782
+
783
+ pub fn access < R > ( & self , f : impl for < ' tcx > FnOnce ( & ' tcx GlobalCtxt < ' tcx > ) -> R ) -> R {
784
+ let read_guard = self . value . read ( ) ;
785
+ let gcx: * const GlobalCtxt < ' _ > = read_guard. unwrap ( ) as * const _ ;
786
+ // SAFETY: We hold the read lock for the `GlobalCtxt` pointer. That prevents
787
+ // `GlobalCtxt::enter` from returning as it would first acquire the write lock.
788
+ // This ensures the `GlobalCtxt` is live during `f`.
789
+ f ( unsafe { & * gcx } )
790
+ }
791
+ }
792
+
744
793
impl < ' tcx > TyCtxt < ' tcx > {
745
794
/// Expects a body and returns its codegen attributes.
746
795
///
@@ -859,6 +908,7 @@ impl<'tcx> TyCtxt<'tcx> {
859
908
query_kinds : & ' tcx [ DepKindStruct < ' tcx > ] ,
860
909
query_system : QuerySystem < ' tcx > ,
861
910
hooks : crate :: hooks:: Providers ,
911
+ current_gcx : CurrentGcx ,
862
912
) -> GlobalCtxt < ' tcx > {
863
913
let data_layout = s. target . parse_data_layout ( ) . unwrap_or_else ( |err| {
864
914
s. dcx ( ) . emit_fatal ( err) ;
@@ -893,6 +943,7 @@ impl<'tcx> TyCtxt<'tcx> {
893
943
canonical_param_env_cache : Default :: default ( ) ,
894
944
data_layout,
895
945
alloc_map : Lock :: new ( interpret:: AllocMap :: new ( ) ) ,
946
+ current_gcx,
896
947
}
897
948
}
898
949
0 commit comments