Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,14 +780,14 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// This likely is a temporary measure. Once we don't have to support the
// non-parallel compiler anymore, we can compile CGUs end-to-end in
// parallel and get rid of the complicated scheduling logic.
let mut pre_compiled_cgus = if tcx.sess.threads() > 1 {
let mut pre_compiled_cgus = if let Some(threads) = tcx.sess.threads() {
tcx.sess.time("compile_first_CGU_batch", || {
// Try to find one CGU to compile per thread.
let cgus: Vec<_> = cgu_reuse
.iter()
.enumerate()
.filter(|&(_, reuse)| reuse == &CguReuse::No)
.take(tcx.sess.threads())
.take(threads)
.collect();

// Compile the found CGUs in parallel.
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,9 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
trace!("run_compiler");

// Set parallel mode before thread pool creation, which will create `Lock`s.
rustc_data_structures::sync::set_dyn_thread_safe_mode(config.opts.unstable_opts.threads > 1);
rustc_data_structures::sync::set_dyn_thread_safe_mode(
config.opts.unstable_opts.threads.is_some(),
);

// Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
Expand All @@ -407,7 +409,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
util::run_in_thread_pool_with_globals(
&early_dcx,
config.opts.edition,
config.opts.unstable_opts.threads,
config.opts.unstable_opts.threads.unwrap_or(1),
&config.extra_symbols,
SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind },
|current_gcx, jobserver_proxy| {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(span_debug, true);
untracked!(span_free_formats, true);
untracked!(temps_dir, Some(String::from("abc")));
untracked!(threads, 99);
untracked!(threads, Some(99));
untracked!(time_llvm_passes, true);
untracked!(time_passes, true);
untracked!(time_passes_format, TimePassesFormat::Json);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2465,7 +2465,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
return;
};

if tcx.sess.threads() != 1 {
if tcx.sess.threads().is_some() {
// Prefetch some queries used by metadata encoding.
// This is not necessary for correctness, but is only done for performance reasons.
// It can be removed if it turns out to cause trouble or be detrimental to performance.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ impl DepGraphData {
let ok = match color {
DepNodeColor::Unknown => true,
DepNodeColor::Red => false,
DepNodeColor::Green(..) => sess.threads() > 1, // Other threads may mark this green
DepNodeColor::Green(..) => sess.threads().is_some(), // Other threads may mark this green
};
if !ok {
panic!("{}", msg())
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
// re-executing the query since `try_start` only checks that the query is not currently
// executing, but another thread may have already completed the query and stores it result
// in the query cache.
if tcx.sess.threads() > 1 {
if tcx.sess.threads().is_some() {
if let Some((value, index)) = query.cache.lookup(&key) {
tcx.prof.query_cache_hit(index.into());
return (value, Some(index));
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2494,11 +2494,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
cg.codegen_units,
);

if unstable_opts.threads == 0 {
early_dcx.early_fatal("value for threads must be a positive non-zero integer");
}

if unstable_opts.threads == parse::MAX_THREADS_CAP {
if unstable_opts.threads == Some(parse::MAX_THREADS_CAP) {
early_dcx.early_warn(format!("number of threads was capped at {}", parse::MAX_THREADS_CAP));
}

Expand Down
33 changes: 18 additions & 15 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ mod desc {
pub(crate) const parse_number: &str = "a number";
pub(crate) const parse_opt_number: &str = parse_number;
pub(crate) const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`";
pub(crate) const parse_threads: &str = parse_number;
pub(crate) const parse_threads: &str = "a number or `sync`";
pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`";
pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`";
pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`";
Expand Down Expand Up @@ -1067,22 +1067,25 @@ pub mod parse {
}
}

pub(crate) fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
let ret = match v.and_then(|s| s.parse().ok()) {
Some(0) => {
*slot = std::thread::available_parallelism().map_or(1, NonZero::<usize>::get);
true
}
Some(i) => {
*slot = i;
true
pub(crate) fn parse_threads(slot: &mut Option<usize>, v: Option<&str>) -> bool {
let n = match v {
Some("sync") => {
*slot = Some(1);
return true;
}
None => false,
Some(s) => match s.parse().ok() {
Some(0) => std::thread::available_parallelism().map_or(1, NonZero::<usize>::get),
Some(i) => i,
None => return false,
},
None => return false,
};

// We want to cap the number of threads here to avoid large numbers like 999999 and compiler panics.
// This solution was suggested here https://github.com/rust-lang/rust/issues/117638#issuecomment-1800925067
*slot = slot.clone().min(MAX_THREADS_CAP);
ret
let n = n.min(MAX_THREADS_CAP);
*slot = (n > 1).then_some(n);
true
}
Comment on lines +1070 to 1089
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will now be clearer as

Suggested change
pub(crate) fn parse_threads(slot: &mut Option<usize>, v: Option<&str>) -> bool {
let n = match v {
Some("sync") => {
*slot = Some(1);
return true;
}
None => false,
Some(s) => match s.parse().ok() {
Some(0) => std::thread::available_parallelism().map_or(1, NonZero::<usize>::get),
Some(i) => i,
None => return false,
},
None => return false,
};
// We want to cap the number of threads here to avoid large numbers like 999999 and compiler panics.
// This solution was suggested here https://github.com/rust-lang/rust/issues/117638#issuecomment-1800925067
*slot = slot.clone().min(MAX_THREADS_CAP);
ret
let n = n.min(MAX_THREADS_CAP);
*slot = (n > 1).then_some(n);
true
}
pub(crate) fn parse_threads(slot: &mut Option<usize>, v: Option<&str>) -> bool {
let Some(s) = v else { return false };
// Configures to use synchronization despite only using one thread.
if s == "sync" {
*slot = Some(1);
return true;
}
let n = match s.parse().ok() {
Some(0) => std::thread::available_parallelism().map_or(1, NonZero::<usize>::get),
Some(i) => i,
None => return false,
};
// We want to cap the number of threads here to avoid large numbers like 999999 and compiler panics.
// This solution was suggested here https://github.com/rust-lang/rust/issues/117638#issuecomment-1800925067
let n = n.min(MAX_THREADS_CAP);
*slot = (n > 1).then_some(n);
true
}

maybe with another comment on the (n > 1).then_some(n) line.


/// Use this for any numeric option that has a static default.
Expand Down Expand Up @@ -2670,12 +2673,12 @@ written to standard error output)"),
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable ThinLTO when possible"),
/// We default to 1 here since we want to behave like
/// We default to None here since we want to behave like
/// a sequential compiler for now. This'll likely be adjusted
/// in the future. Note that -Zthreads=0 is the way to get
/// the num_cpus behavior.
#[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
threads: usize = (1, parse_threads, [UNTRACKED],
threads: Option<usize> = (None, parse_threads, [UNTRACKED],
"use a thread pool with N threads"),
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each LLVM pass (default: no)"),
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,10 +813,12 @@ impl Session {
.unwrap_or(self.panic_strategy().unwinds() || self.target.default_uwtable)
}

/// Returns the number of query threads that should be used for this
/// compilation
/// Returns the number of threads used for the thread pool.
///
/// `None` means thread pool is not used and synchronization is disabled.
/// `Some(n)` means synchronization is enabled with `n` worker threads.
#[inline]
pub fn threads(&self) -> usize {
pub fn threads(&self) -> Option<usize> {
self.opts.unstable_opts.threads
}

Expand Down
Loading