-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Replace LockCell with atomic types #56614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,10 @@ use util::common::{duration_to_secs_str, ErrorReported}; | |
use util::common::ProfileQueriesMsg; | ||
|
||
use rustc_data_structures::base_n; | ||
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock}; | ||
use rustc_data_structures::sync::{ | ||
self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, AtomicBool, Ordering, | ||
Ordering::SeqCst, | ||
}; | ||
|
||
use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability}; | ||
use errors::emitter::{Emitter, EmitterWriter}; | ||
|
@@ -41,7 +44,6 @@ use std::io::Write; | |
use std::path::PathBuf; | ||
use std::time::Duration; | ||
use std::sync::mpsc; | ||
use std::sync::atomic::{AtomicUsize, Ordering}; | ||
|
||
mod code_stats; | ||
pub mod config; | ||
|
@@ -138,15 +140,15 @@ pub struct Session { | |
/// If -zfuel=crate=n is specified, Some(crate). | ||
optimization_fuel_crate: Option<String>, | ||
/// If -zfuel=crate=n is specified, initially set to n. Otherwise 0. | ||
optimization_fuel_limit: LockCell<u64>, | ||
optimization_fuel_limit: AtomicU64, | ||
/// We're rejecting all further optimizations. | ||
out_of_fuel: LockCell<bool>, | ||
out_of_fuel: AtomicBool, | ||
|
||
// The next two are public because the driver needs to read them. | ||
/// If -zprint-fuel=crate, Some(crate). | ||
pub print_fuel_crate: Option<String>, | ||
/// Always set to zero and incremented so that we can print fuel expended by a crate. | ||
pub print_fuel: LockCell<u64>, | ||
pub print_fuel: AtomicU64, | ||
|
||
/// Loaded up early on in the initialization of this `Session` to avoid | ||
/// false positives about a job server in our environment. | ||
|
@@ -857,32 +859,43 @@ impl Session { | |
self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed)); | ||
} | ||
|
||
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. | ||
/// This expends fuel if applicable, and records fuel if applicable. | ||
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { | ||
#[inline(never)] | ||
#[cold] | ||
pub fn consider_optimizing_cold<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { | ||
let mut ret = true; | ||
if let Some(ref c) = self.optimization_fuel_crate { | ||
if c == crate_name { | ||
assert_eq!(self.query_threads(), 1); | ||
let fuel = self.optimization_fuel_limit.get(); | ||
let fuel = self.optimization_fuel_limit.load(SeqCst); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is pretty racy I think. This should all be in a cas loop and the other section (for print_fuel) should be a fetch add, right? Granted it was racy before even with locks, but still. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It asserts that the compiler is running in single-threaded mode, so it should be fine. It would be nicer though if the two fields in question would be behind a single lock. |
||
ret = fuel != 0; | ||
if fuel == 0 && !self.out_of_fuel.get() { | ||
if fuel == 0 && !self.out_of_fuel.load(SeqCst) { | ||
eprintln!("optimization-fuel-exhausted: {}", msg()); | ||
self.out_of_fuel.set(true); | ||
self.out_of_fuel.store(true, SeqCst); | ||
} else if fuel > 0 { | ||
self.optimization_fuel_limit.set(fuel - 1); | ||
self.optimization_fuel_limit.store(fuel - 1, SeqCst); | ||
} | ||
} | ||
} | ||
if let Some(ref c) = self.print_fuel_crate { | ||
if c == crate_name { | ||
assert_eq!(self.query_threads(), 1); | ||
self.print_fuel.set(self.print_fuel.get() + 1); | ||
self.print_fuel.store(self.print_fuel.load(SeqCst) + 1, SeqCst); | ||
} | ||
} | ||
ret | ||
} | ||
|
||
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. | ||
/// This expends fuel if applicable, and records fuel if applicable. | ||
#[inline(always)] | ||
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { | ||
if likely!(self.optimization_fuel_crate.is_none() && self.print_fuel_crate.is_none()) { | ||
true | ||
} else { | ||
self.consider_optimizing_cold(crate_name, msg) | ||
} | ||
} | ||
|
||
/// Returns the number of query threads that should be used for this | ||
/// compilation | ||
pub fn query_threads_from_opts(opts: &config::Options) -> usize { | ||
|
@@ -1128,9 +1141,9 @@ pub fn build_session_( | |
|
||
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone()); | ||
let optimization_fuel_limit = | ||
LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0)); | ||
AtomicU64::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0)); | ||
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone(); | ||
let print_fuel = LockCell::new(0); | ||
let print_fuel = AtomicU64::new(0); | ||
|
||
let working_dir = env::current_dir().unwrap_or_else(|e| | ||
p_s.span_diagnostic | ||
|
@@ -1195,7 +1208,7 @@ pub fn build_session_( | |
optimization_fuel_limit, | ||
print_fuel_crate, | ||
print_fuel, | ||
out_of_fuel: LockCell::new(false), | ||
out_of_fuel: AtomicBool::new(false), | ||
// Note that this is unsafe because it may misinterpret file descriptors | ||
// on Unix as jobserver file descriptors. We hopefully execute this near | ||
// the beginning of the process though to ensure we don't get false | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does splitting this into two functions really translate to faster compile-times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used in layout computation. Not sure how hot it is, but it probably won't hurt. Especially if we want to add more MIR optimizations (and debug them)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway this PR is mostly about getting rid of
LockCell
, I just found this on the wayThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. It does hurt code quality though as it makes things more complicated and thus harder to read and maintain. I personally prefer not to do things like this without evidence that it carries it's weight.