Skip to content

Commit 8aafed8

Browse files
committed
Add sync option to -Z threads to force synchronization on one thread
1 parent 4feb722 commit 8aafed8

9 files changed

Lines changed: 33 additions & 32 deletions

File tree

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,14 +780,14 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
780780
// This likely is a temporary measure. Once we don't have to support the
781781
// non-parallel compiler anymore, we can compile CGUs end-to-end in
782782
// parallel and get rid of the complicated scheduling logic.
783-
let mut pre_compiled_cgus = if tcx.sess.threads() > 1 {
783+
let mut pre_compiled_cgus = if let Some(threads) = tcx.sess.threads() {
784784
tcx.sess.time("compile_first_CGU_batch", || {
785785
// Try to find one CGU to compile per thread.
786786
let cgus: Vec<_> = cgu_reuse
787787
.iter()
788788
.enumerate()
789789
.filter(|&(_, reuse)| reuse == &CguReuse::No)
790-
.take(tcx.sess.threads())
790+
.take(threads)
791791
.collect();
792792

793793
// Compile the found CGUs in parallel.

compiler/rustc_interface/src/interface.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,9 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
385385
trace!("run_compiler");
386386

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

390392
// Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
391393
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
@@ -407,7 +409,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
407409
util::run_in_thread_pool_with_globals(
408410
&early_dcx,
409411
config.opts.edition,
410-
config.opts.unstable_opts.threads,
412+
config.opts.unstable_opts.threads.unwrap_or(1),
411413
&config.extra_symbols,
412414
SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind },
413415
|current_gcx, jobserver_proxy| {

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ fn test_unstable_options_tracking_hash() {
734734
untracked!(span_debug, true);
735735
untracked!(span_free_formats, true);
736736
untracked!(temps_dir, Some(String::from("abc")));
737-
untracked!(threads, 99);
737+
untracked!(threads, Some(99));
738738
untracked!(time_llvm_passes, true);
739739
untracked!(time_passes, true);
740740
untracked!(time_passes_format, TimePassesFormat::Json);

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2465,7 +2465,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
24652465
return;
24662466
};
24672467

2468-
if tcx.sess.threads() != 1 {
2468+
if tcx.sess.threads().is_some() {
24692469
// Prefetch some queries used by metadata encoding.
24702470
// This is not necessary for correctness, but is only done for performance reasons.
24712471
// It can be removed if it turns out to cause trouble or be detrimental to performance.

compiler/rustc_middle/src/dep_graph/graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ impl DepGraphData {
629629
let ok = match color {
630630
DepNodeColor::Unknown => true,
631631
DepNodeColor::Red => false,
632-
DepNodeColor::Green(..) => sess.threads() > 1, // Other threads may mark this green
632+
DepNodeColor::Green(..) => sess.threads().is_some(), // Other threads may mark this green
633633
};
634634
if !ok {
635635
panic!("{}", msg())

compiler/rustc_query_impl/src/execution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
294294
// re-executing the query since `try_start` only checks that the query is not currently
295295
// executing, but another thread may have already completed the query and stores it result
296296
// in the query cache.
297-
if tcx.sess.threads() > 1 {
297+
if tcx.sess.threads().is_some() {
298298
if let Some((value, index)) = query.cache.lookup(&key) {
299299
tcx.prof.query_cache_hit(index.into());
300300
return (value, Some(index));

compiler/rustc_session/src/config.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,11 +2494,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
24942494
cg.codegen_units,
24952495
);
24962496

2497-
if unstable_opts.threads == 0 {
2498-
early_dcx.early_fatal("value for threads must be a positive non-zero integer");
2499-
}
2500-
2501-
if unstable_opts.threads == parse::MAX_THREADS_CAP {
2497+
if unstable_opts.threads == Some(parse::MAX_THREADS_CAP) {
25022498
early_dcx.early_warn(format!("number of threads was capped at {}", parse::MAX_THREADS_CAP));
25032499
}
25042500

compiler/rustc_session/src/options.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ mod desc {
759759
pub(crate) const parse_number: &str = "a number";
760760
pub(crate) const parse_opt_number: &str = parse_number;
761761
pub(crate) const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`";
762-
pub(crate) const parse_threads: &str = parse_number;
762+
pub(crate) const parse_threads: &str = "a number or `sync`";
763763
pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`";
764764
pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`";
765765
pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`";
@@ -1067,22 +1067,23 @@ pub mod parse {
10671067
}
10681068
}
10691069

1070-
pub(crate) fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
1071-
let ret = match v.and_then(|s| s.parse().ok()) {
1072-
Some(0) => {
1073-
*slot = std::thread::available_parallelism().map_or(1, NonZero::<usize>::get);
1074-
true
1075-
}
1076-
Some(i) => {
1077-
*slot = i;
1078-
true
1079-
}
1080-
None => false,
1070+
pub(crate) fn parse_threads(slot: &mut Option<usize>, v: Option<&str>) -> bool {
1071+
let Some(s) = v else { return false };
1072+
if s == "sync" {
1073+
// Enable synchronization despite only using one thread.
1074+
*slot = Some(1);
1075+
return true;
1076+
}
1077+
let n = match s.parse().ok() {
1078+
Some(0) => std::thread::available_parallelism().map_or(1, NonZero::<usize>::get),
1079+
Some(i) => i,
1080+
None => return false,
10811081
};
10821082
// We want to cap the number of threads here to avoid large numbers like 999999 and compiler panics.
10831083
// This solution was suggested here https://github.com/rust-lang/rust/issues/117638#issuecomment-1800925067
1084-
*slot = slot.clone().min(MAX_THREADS_CAP);
1085-
ret
1084+
let n = n.min(MAX_THREADS_CAP);
1085+
*slot = (n > 1).then_some(n); // Enable synchronization if we're using more than one thread.
1086+
true
10861087
}
10871088

10881089
/// Use this for any numeric option that has a static default.
@@ -2670,12 +2671,12 @@ written to standard error output)"),
26702671
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
26712672
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
26722673
"enable ThinLTO when possible"),
2673-
/// We default to 1 here since we want to behave like
2674+
/// We default to None here since we want to behave like
26742675
/// a sequential compiler for now. This'll likely be adjusted
26752676
/// in the future. Note that -Zthreads=0 is the way to get
26762677
/// the num_cpus behavior.
26772678
#[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
2678-
threads: usize = (1, parse_threads, [UNTRACKED],
2679+
threads: Option<usize> = (None, parse_threads, [UNTRACKED],
26792680
"use a thread pool with N threads"),
26802681
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
26812682
"measure time of each LLVM pass (default: no)"),

compiler/rustc_session/src/session.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -813,10 +813,12 @@ impl Session {
813813
.unwrap_or(self.panic_strategy().unwinds() || self.target.default_uwtable)
814814
}
815815

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

0 commit comments

Comments
 (0)