mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Clarify run_in_thread_pool_with_globals
.
- Make the structure of the two variants more similar. - Add some comments. - Move various conditional `use` items inside the function that uses them. - Inline some closures.
This commit is contained in:
parent
2efc90e738
commit
cf13d9143d
@ -190,6 +190,7 @@ impl<'a, 'b> RunCompiler<'a, 'b> {
|
|||||||
run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
|
run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_compiler(
|
fn run_compiler(
|
||||||
at_args: &[String],
|
at_args: &[String],
|
||||||
callbacks: &mut (dyn Callbacks + Send),
|
callbacks: &mut (dyn Callbacks + Send),
|
||||||
|
@ -3,14 +3,8 @@ use libloading::Library;
|
|||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
#[cfg(parallel_compiler)]
|
|
||||||
use rustc_data_structures::jobserver;
|
|
||||||
use rustc_errors::registry::Registry;
|
use rustc_errors::registry::Registry;
|
||||||
#[cfg(parallel_compiler)]
|
|
||||||
use rustc_middle::ty::tls;
|
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
#[cfg(parallel_compiler)]
|
|
||||||
use rustc_query_impl::{QueryContext, QueryCtxt};
|
|
||||||
use rustc_session as session;
|
use rustc_session as session;
|
||||||
use rustc_session::config::CheckCfg;
|
use rustc_session::config::CheckCfg;
|
||||||
use rustc_session::config::{self, CrateType};
|
use rustc_session::config::{self, CrateType};
|
||||||
@ -25,8 +19,6 @@ use rustc_span::symbol::{sym, Symbol};
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
#[cfg(not(parallel_compiler))]
|
|
||||||
use std::panic;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
@ -135,13 +127,20 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
|||||||
_threads: usize,
|
_threads: usize,
|
||||||
f: F,
|
f: F,
|
||||||
) -> R {
|
) -> R {
|
||||||
// The thread pool is a single thread in the non-parallel compiler.
|
// The "thread pool" is a single spawned thread in the non-parallel
|
||||||
thread::scope(|s| {
|
// compiler. We run on a spawned thread instead of the main thread (a) to
|
||||||
let mut builder = thread::Builder::new().name("rustc".to_string());
|
// provide control over the stack size, and (b) to increase similarity with
|
||||||
if let Some(size) = get_stack_size() {
|
// the parallel compiler, in particular to ensure there is no accidental
|
||||||
builder = builder.stack_size(size);
|
// sharing of data between the main thread and the compilation thread
|
||||||
}
|
// (which might cause problems for the parallel compiler).
|
||||||
|
let mut builder = thread::Builder::new().name("rustc".to_string());
|
||||||
|
if let Some(size) = get_stack_size() {
|
||||||
|
builder = builder.stack_size(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We build the session globals and run `f` on the spawned thread, because
|
||||||
|
// `SessionGlobals` does not impl `Send` in the non-parallel compiler.
|
||||||
|
thread::scope(|s| {
|
||||||
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
|
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
|
||||||
// name contains null bytes.
|
// name contains null bytes.
|
||||||
let r = builder
|
let r = builder
|
||||||
@ -151,55 +150,57 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
|||||||
|
|
||||||
match r {
|
match r {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => panic::resume_unwind(e),
|
Err(e) => std::panic::resume_unwind(e),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new thread and forwards information in thread locals to it.
|
|
||||||
/// The new thread runs the deadlock handler.
|
|
||||||
/// Must only be called when a deadlock is about to happen.
|
|
||||||
#[cfg(parallel_compiler)]
|
|
||||||
unsafe fn handle_deadlock() {
|
|
||||||
let registry = rustc_rayon_core::Registry::current();
|
|
||||||
|
|
||||||
let query_map = tls::with(|tcx| {
|
|
||||||
QueryCtxt::from_tcx(tcx)
|
|
||||||
.try_collect_active_jobs()
|
|
||||||
.expect("active jobs shouldn't be locked in deadlock handler")
|
|
||||||
});
|
|
||||||
thread::spawn(move || rustc_query_impl::deadlock(query_map, ®istry));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
f: F,
|
f: F,
|
||||||
) -> R {
|
) -> R {
|
||||||
let mut config = rayon::ThreadPoolBuilder::new()
|
use rustc_data_structures::jobserver;
|
||||||
|
use rustc_middle::ty::tls;
|
||||||
|
use rustc_query_impl::{deadlock, QueryContext, QueryCtxt};
|
||||||
|
|
||||||
|
let mut builder = rayon::ThreadPoolBuilder::new()
|
||||||
.thread_name(|_| "rustc".to_string())
|
.thread_name(|_| "rustc".to_string())
|
||||||
.acquire_thread_handler(jobserver::acquire_thread)
|
.acquire_thread_handler(jobserver::acquire_thread)
|
||||||
.release_thread_handler(jobserver::release_thread)
|
.release_thread_handler(jobserver::release_thread)
|
||||||
.num_threads(threads)
|
.num_threads(threads)
|
||||||
.deadlock_handler(|| unsafe { handle_deadlock() });
|
.deadlock_handler(|| {
|
||||||
|
// On deadlock, creates a new thread and forwards information in thread
|
||||||
|
// locals to it. The new thread runs the deadlock handler.
|
||||||
|
let query_map = tls::with(|tcx| {
|
||||||
|
QueryCtxt::from_tcx(tcx)
|
||||||
|
.try_collect_active_jobs()
|
||||||
|
.expect("active jobs shouldn't be locked in deadlock handler")
|
||||||
|
});
|
||||||
|
let registry = rustc_rayon_core::Registry::current();
|
||||||
|
thread::spawn(move || deadlock(query_map, ®istry));
|
||||||
|
});
|
||||||
if let Some(size) = get_stack_size() {
|
if let Some(size) = get_stack_size() {
|
||||||
config = config.stack_size(size);
|
builder = builder.stack_size(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);
|
// We create the session globals on the main thread, then create the thread
|
||||||
|
// pool. Upon creation, each worker thread created gets a copy of the
|
||||||
|
// session globals in TLS. This is possible because `SessionGlobals` impls
|
||||||
|
// `Send` in the parallel compiler.
|
||||||
rustc_span::create_session_globals_then(edition, || {
|
rustc_span::create_session_globals_then(edition, || {
|
||||||
rustc_span::with_session_globals(|session_globals| {
|
rustc_span::with_session_globals(|session_globals| {
|
||||||
// The main handler runs for each Rayon worker thread and sets up
|
builder
|
||||||
// the thread local rustc uses. `session_globals` is captured and set
|
.build_scoped(
|
||||||
// on the new threads.
|
// Initialize each new worker thread when created.
|
||||||
let main_handler = move |thread: rayon::ThreadBuilder| {
|
move |thread: rayon::ThreadBuilder| {
|
||||||
rustc_span::set_session_globals_then(session_globals, || thread.run())
|
rustc_span::set_session_globals_then(session_globals, || thread.run())
|
||||||
};
|
},
|
||||||
|
// Run `f` on the first thread in the thread pool.
|
||||||
config.build_scoped(main_handler, with_pool).unwrap()
|
move |pool: &rayon::ThreadPool| pool.install(f),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user