@@ -3,14 +3,8 @@ use libloading::Library;
3
3
use rustc_ast as ast;
4
4
use rustc_codegen_ssa:: traits:: CodegenBackend ;
5
5
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
6
- #[ cfg( parallel_compiler) ]
7
- use rustc_data_structures:: jobserver;
8
6
use rustc_errors:: registry:: Registry ;
9
- #[ cfg( parallel_compiler) ]
10
- use rustc_middle:: ty:: tls;
11
7
use rustc_parse:: validate_attr;
12
- #[ cfg( parallel_compiler) ]
13
- use rustc_query_impl:: { QueryContext , QueryCtxt } ;
14
8
use rustc_session as session;
15
9
use rustc_session:: config:: CheckCfg ;
16
10
use rustc_session:: config:: { self , CrateType } ;
@@ -25,8 +19,6 @@ use rustc_span::symbol::{sym, Symbol};
25
19
use std:: env;
26
20
use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
27
21
use std:: mem;
28
- #[ cfg( not( parallel_compiler) ) ]
29
- use std:: panic;
30
22
use std:: path:: { Path , PathBuf } ;
31
23
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
32
24
use std:: sync:: OnceLock ;
@@ -135,13 +127,20 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
135
127
_threads : usize ,
136
128
f : F ,
137
129
) -> R {
138
- // The thread pool is a single thread in the non-parallel compiler.
139
- thread:: scope ( |s| {
140
- let mut builder = thread:: Builder :: new ( ) . name ( "rustc" . to_string ( ) ) ;
141
- if let Some ( size) = get_stack_size ( ) {
142
- builder = builder. stack_size ( size) ;
143
- }
130
+ // The "thread pool" is a single spawned thread in the non-parallel
131
+ // compiler. We run on a spawned thread instead of the main thread (a) to
132
+ // provide control over the stack size, and (b) to increase similarity with
133
+ // the parallel compiler, in particular to ensure there is no accidental
134
+ // sharing of data between the main thread and the compilation thread
135
+ // (which might cause problems for the parallel compiler).
136
+ let mut builder = thread:: Builder :: new ( ) . name ( "rustc" . to_string ( ) ) ;
137
+ if let Some ( size) = get_stack_size ( ) {
138
+ builder = builder. stack_size ( size) ;
139
+ }
144
140
141
+ // We build the session globals and run `f` on the spawned thread, because
142
+ // `SessionGlobals` does not impl `Send` in the non-parallel compiler.
143
+ thread:: scope ( |s| {
145
144
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
146
145
// name contains null bytes.
147
146
let r = builder
@@ -151,55 +150,57 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
151
150
152
151
match r {
153
152
Ok ( v) => v,
154
- Err ( e) => panic:: resume_unwind ( e) ,
153
+ Err ( e) => std :: panic:: resume_unwind ( e) ,
155
154
}
156
155
} )
157
156
}
158
157
159
- /// Creates a new thread and forwards information in thread locals to it.
160
- /// The new thread runs the deadlock handler.
161
- /// Must only be called when a deadlock is about to happen.
162
- #[ cfg( parallel_compiler) ]
163
- unsafe fn handle_deadlock ( ) {
164
- let registry = rustc_rayon_core:: Registry :: current ( ) ;
165
-
166
- let query_map = tls:: with ( |tcx| {
167
- QueryCtxt :: from_tcx ( tcx)
168
- . try_collect_active_jobs ( )
169
- . expect ( "active jobs shouldn't be locked in deadlock handler" )
170
- } ) ;
171
- thread:: spawn ( move || rustc_query_impl:: deadlock ( query_map, & registry) ) ;
172
- }
173
-
174
158
#[ cfg( parallel_compiler) ]
175
159
pub ( crate ) fn run_in_thread_pool_with_globals < F : FnOnce ( ) -> R + Send , R : Send > (
176
160
edition : Edition ,
177
161
threads : usize ,
178
162
f : F ,
179
163
) -> R {
180
- let mut config = rayon:: ThreadPoolBuilder :: new ( )
164
+ use rustc_data_structures:: jobserver;
165
+ use rustc_middle:: ty:: tls;
166
+ use rustc_query_impl:: { deadlock, QueryContext , QueryCtxt } ;
167
+
168
+ let mut builder = rayon:: ThreadPoolBuilder :: new ( )
181
169
. thread_name ( |_| "rustc" . to_string ( ) )
182
170
. acquire_thread_handler ( jobserver:: acquire_thread)
183
171
. release_thread_handler ( jobserver:: release_thread)
184
172
. num_threads ( threads)
185
- . deadlock_handler ( || unsafe { handle_deadlock ( ) } ) ;
186
-
173
+ . deadlock_handler ( || {
174
+ // On deadlock, creates a new thread and forwards information in thread
175
+ // locals to it. The new thread runs the deadlock handler.
176
+ let query_map = tls:: with ( |tcx| {
177
+ QueryCtxt :: from_tcx ( tcx)
178
+ . try_collect_active_jobs ( )
179
+ . expect ( "active jobs shouldn't be locked in deadlock handler" )
180
+ } ) ;
181
+ let registry = rustc_rayon_core:: Registry :: current ( ) ;
182
+ thread:: spawn ( move || deadlock ( query_map, & registry) ) ;
183
+ } ) ;
187
184
if let Some ( size) = get_stack_size ( ) {
188
- config = config . stack_size ( size) ;
185
+ builder = builder . stack_size ( size) ;
189
186
}
190
187
191
- let with_pool = move |pool : & rayon:: ThreadPool | pool. install ( f) ;
192
-
188
+ // We create the session globals on the main thread, then create the thread
189
+ // pool. Upon creation, each worker thread created gets a copy of the
190
+ // session globals in TLS. This is possible because `SessionGlobals` impls
191
+ // `Send` in the parallel compiler.
193
192
rustc_span:: create_session_globals_then ( edition, || {
194
193
rustc_span:: with_session_globals ( |session_globals| {
195
- // The main handler runs for each Rayon worker thread and sets up
196
- // the thread local rustc uses. `session_globals` is captured and set
197
- // on the new threads.
198
- let main_handler = move |thread : rayon:: ThreadBuilder | {
199
- rustc_span:: set_session_globals_then ( session_globals, || thread. run ( ) )
200
- } ;
201
-
202
- config. build_scoped ( main_handler, with_pool) . unwrap ( )
194
+ builder
195
+ . build_scoped (
196
+ // Initialize each new worker thread when created.
197
+ move |thread : rayon:: ThreadBuilder | {
198
+ rustc_span:: set_session_globals_then ( session_globals, || thread. run ( ) )
199
+ } ,
200
+ // Run `f` on the first thread in the thread pool.
201
+ move |pool : & rayon:: ThreadPool | pool. install ( f) ,
202
+ )
203
+ . unwrap ( )
203
204
} )
204
205
} )
205
206
}
0 commit comments