Skip to content

Commit 8f20507

Browse files
committed
Replace LockCell with atomic types
# Conflicts: # src/librustc_data_structures/lib.rs
1 parent a97b949 commit 8f20507

File tree

5 files changed

+100
-175
lines changed

5 files changed

+100
-175
lines changed

src/librustc/session/mod.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use util::common::{duration_to_secs_str, ErrorReported};
2626
use util::common::ProfileQueriesMsg;
2727

2828
use rustc_data_structures::base_n;
29-
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
29+
use rustc_data_structures::sync::{
30+
self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, AtomicBool, Ordering,
31+
Ordering::SeqCst,
32+
};
3033

3134
use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
3235
use errors::emitter::{Emitter, EmitterWriter};
@@ -51,7 +54,6 @@ use std::io::Write;
5154
use std::path::PathBuf;
5255
use std::time::Duration;
5356
use std::sync::mpsc;
54-
use std::sync::atomic::{AtomicUsize, Ordering};
5557

5658
mod code_stats;
5759
pub mod config;
@@ -148,15 +150,15 @@ pub struct Session {
148150
/// If -zfuel=crate=n is specified, Some(crate).
149151
optimization_fuel_crate: Option<String>,
150152
/// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
151-
optimization_fuel_limit: LockCell<u64>,
153+
optimization_fuel_limit: AtomicU64,
152154
/// We're rejecting all further optimizations.
153-
out_of_fuel: LockCell<bool>,
155+
out_of_fuel: AtomicBool,
154156

155157
// The next two are public because the driver needs to read them.
156158
/// If -zprint-fuel=crate, Some(crate).
157159
pub print_fuel_crate: Option<String>,
158160
/// Always set to zero and incremented so that we can print fuel expended by a crate.
159-
pub print_fuel: LockCell<u64>,
161+
pub print_fuel: AtomicU64,
160162

161163
/// Loaded up early on in the initialization of this `Session` to avoid
162164
/// false positives about a job server in our environment.
@@ -867,32 +869,43 @@ impl Session {
867869
self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed));
868870
}
869871

870-
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
871-
/// This expends fuel if applicable, and records fuel if applicable.
872-
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
872+
#[inline(never)]
873+
#[cold]
874+
pub fn consider_optimizing_cold<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
873875
let mut ret = true;
874876
if let Some(ref c) = self.optimization_fuel_crate {
875877
if c == crate_name {
876878
assert_eq!(self.query_threads(), 1);
877-
let fuel = self.optimization_fuel_limit.get();
879+
let fuel = self.optimization_fuel_limit.load(SeqCst);
878880
ret = fuel != 0;
879-
if fuel == 0 && !self.out_of_fuel.get() {
881+
if fuel == 0 && !self.out_of_fuel.load(SeqCst) {
880882
eprintln!("optimization-fuel-exhausted: {}", msg());
881-
self.out_of_fuel.set(true);
883+
self.out_of_fuel.store(true, SeqCst);
882884
} else if fuel > 0 {
883-
self.optimization_fuel_limit.set(fuel - 1);
885+
self.optimization_fuel_limit.store(fuel - 1, SeqCst);
884886
}
885887
}
886888
}
887889
if let Some(ref c) = self.print_fuel_crate {
888890
if c == crate_name {
889891
assert_eq!(self.query_threads(), 1);
890-
self.print_fuel.set(self.print_fuel.get() + 1);
892+
self.print_fuel.store(self.print_fuel.load(SeqCst) + 1, SeqCst);
891893
}
892894
}
893895
ret
894896
}
895897

898+
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
899+
/// This expends fuel if applicable, and records fuel if applicable.
900+
#[inline(always)]
901+
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
902+
if likely!(self.optimization_fuel_crate.is_none() && self.print_fuel_crate.is_none()) {
903+
true
904+
} else {
905+
self.consider_optimizing_cold(crate_name, msg)
906+
}
907+
}
908+
896909
/// Returns the number of query threads that should be used for this
897910
/// compilation
898911
pub fn query_threads_from_opts(opts: &config::Options) -> usize {
@@ -1138,9 +1151,9 @@ pub fn build_session_(
11381151

11391152
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
11401153
let optimization_fuel_limit =
1141-
LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
1154+
AtomicU64::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
11421155
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
1143-
let print_fuel = LockCell::new(0);
1156+
let print_fuel = AtomicU64::new(0);
11441157

11451158
let working_dir = env::current_dir().unwrap_or_else(|e|
11461159
p_s.span_diagnostic
@@ -1205,7 +1218,7 @@ pub fn build_session_(
12051218
optimization_fuel_limit,
12061219
print_fuel_crate,
12071220
print_fuel,
1208-
out_of_fuel: LockCell::new(false),
1221+
out_of_fuel: AtomicBool::new(false),
12091222
// Note that this is unsafe because it may misinterpret file descriptors
12101223
// on Unix as jobserver file descriptors. We hopefully execute this near
12111224
// the beginning of the process though to ensure we don't get false

src/librustc_data_structures/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(hash_raw_entry)]
3232
#![feature(stmt_expr_attributes)]
3333
#![feature(core_intrinsics)]
34+
#![feature(integer_atomics)]
3435

3536
#![cfg_attr(unix, feature(libc))]
3637
#![cfg_attr(test, feature(test))]

src/librustc_data_structures/sync.rs

Lines changed: 61 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_queries) is true,
2121
//! `RefCell` otherwise.
2222
//!
23-
//! `LockCell` is a thread safe version of `Cell`, with `set` and `get` operations.
24-
//! It can never deadlock. It uses `Cell` when
25-
//! cfg!(parallel_queries) is false, otherwise it is a `Lock`.
26-
//!
2723
//! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
2824
//!
2925
//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise.
@@ -33,11 +29,7 @@
3329
3430
use std::collections::HashMap;
3531
use std::hash::{Hash, BuildHasher};
36-
use std::cmp::Ordering;
3732
use std::marker::PhantomData;
38-
use std::fmt::Debug;
39-
use std::fmt::Formatter;
40-
use std::fmt;
4133
use std::ops::{Deref, DerefMut};
4234
use owning_ref::{Erased, OwningRef};
4335

@@ -64,6 +56,9 @@ pub fn serial_scope<F, R>(f: F) -> R
6456
f(&SerialScope)
6557
}
6658

59+
pub use std::sync::atomic::Ordering::SeqCst;
60+
pub use std::sync::atomic::Ordering;
61+
6762
cfg_if! {
6863
if #[cfg(not(parallel_queries))] {
6964
pub auto trait Send {}
@@ -79,6 +74,62 @@ cfg_if! {
7974
}
8075
}
8176

77+
use std::ops::Add;
78+
79+
#[derive(Debug)]
80+
pub struct Atomic<T: Copy>(Cell<T>);
81+
82+
impl<T: Copy> Atomic<T> {
83+
pub fn new(v: T) -> Self {
84+
Atomic(Cell::new(v))
85+
}
86+
}
87+
88+
impl<T: Copy + PartialEq> Atomic<T> {
89+
pub fn into_inner(self) -> T {
90+
self.0.into_inner()
91+
}
92+
93+
pub fn load(&self, _: Ordering) -> T {
94+
self.0.get()
95+
}
96+
97+
pub fn store(&self, val: T, _: Ordering) {
98+
self.0.set(val)
99+
}
100+
101+
pub fn swap(&self, val: T, _: Ordering) -> T {
102+
self.0.replace(val)
103+
}
104+
105+
pub fn compare_exchange(&self,
106+
current: T,
107+
new: T,
108+
_: Ordering,
109+
_: Ordering)
110+
-> Result<T, T> {
111+
let read = self.0.get();
112+
if read == current {
113+
self.0.set(new);
114+
Ok(read)
115+
} else {
116+
Err(read)
117+
}
118+
}
119+
}
120+
121+
impl<T: Add<Output=T> + Copy> Atomic<T> {
122+
pub fn fetch_add(&self, val: T, _: Ordering) -> T {
123+
let old = self.0.get();
124+
self.0.set(old + val);
125+
old
126+
}
127+
}
128+
129+
pub type AtomicUsize = Atomic<usize>;
130+
pub type AtomicBool = Atomic<bool>;
131+
pub type AtomicU64 = Atomic<u64>;
132+
82133
pub use self::serial_join as join;
83134
pub use self::serial_scope as scope;
84135

@@ -170,47 +221,6 @@ cfg_if! {
170221
MTLock(self.0.clone())
171222
}
172223
}
173-
174-
pub struct LockCell<T>(Cell<T>);
175-
176-
impl<T> LockCell<T> {
177-
#[inline(always)]
178-
pub fn new(inner: T) -> Self {
179-
LockCell(Cell::new(inner))
180-
}
181-
182-
#[inline(always)]
183-
pub fn into_inner(self) -> T {
184-
self.0.into_inner()
185-
}
186-
187-
#[inline(always)]
188-
pub fn set(&self, new_inner: T) {
189-
self.0.set(new_inner);
190-
}
191-
192-
#[inline(always)]
193-
pub fn get(&self) -> T where T: Copy {
194-
self.0.get()
195-
}
196-
197-
#[inline(always)]
198-
pub fn set_mut(&mut self, new_inner: T) {
199-
self.0.set(new_inner);
200-
}
201-
202-
#[inline(always)]
203-
pub fn get_mut(&mut self) -> T where T: Copy {
204-
self.0.get()
205-
}
206-
}
207-
208-
impl<T> LockCell<Option<T>> {
209-
#[inline(always)]
210-
pub fn take(&self) -> Option<T> {
211-
unsafe { (*self.0.as_ptr()).take() }
212-
}
213-
}
214224
} else {
215225
pub use std::marker::Send as Send;
216226
pub use std::marker::Sync as Sync;
@@ -223,6 +233,8 @@ cfg_if! {
223233
pub use parking_lot::MutexGuard as LockGuard;
224234
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
225235

236+
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
237+
226238
pub use std::sync::Arc as Lrc;
227239
pub use std::sync::Weak as Weak;
228240

@@ -288,47 +300,6 @@ cfg_if! {
288300
v.erase_send_sync_owner()
289301
}}
290302
}
291-
292-
pub struct LockCell<T>(Lock<T>);
293-
294-
impl<T> LockCell<T> {
295-
#[inline(always)]
296-
pub fn new(inner: T) -> Self {
297-
LockCell(Lock::new(inner))
298-
}
299-
300-
#[inline(always)]
301-
pub fn into_inner(self) -> T {
302-
self.0.into_inner()
303-
}
304-
305-
#[inline(always)]
306-
pub fn set(&self, new_inner: T) {
307-
*self.0.lock() = new_inner;
308-
}
309-
310-
#[inline(always)]
311-
pub fn get(&self) -> T where T: Copy {
312-
*self.0.lock()
313-
}
314-
315-
#[inline(always)]
316-
pub fn set_mut(&mut self, new_inner: T) {
317-
*self.0.get_mut() = new_inner;
318-
}
319-
320-
#[inline(always)]
321-
pub fn get_mut(&mut self) -> T where T: Copy {
322-
*self.0.get_mut()
323-
}
324-
}
325-
326-
impl<T> LockCell<Option<T>> {
327-
#[inline(always)]
328-
pub fn take(&self) -> Option<T> {
329-
self.0.lock().take()
330-
}
331-
}
332303
}
333304
}
334305

@@ -476,65 +447,6 @@ impl<T> Once<T> {
476447
}
477448
}
478449

479-
impl<T: Copy + Debug> Debug for LockCell<T> {
480-
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
481-
f.debug_struct("LockCell")
482-
.field("value", &self.get())
483-
.finish()
484-
}
485-
}
486-
487-
impl<T:Default> Default for LockCell<T> {
488-
/// Creates a `LockCell<T>`, with the `Default` value for T.
489-
#[inline]
490-
fn default() -> LockCell<T> {
491-
LockCell::new(Default::default())
492-
}
493-
}
494-
495-
impl<T:PartialEq + Copy> PartialEq for LockCell<T> {
496-
#[inline]
497-
fn eq(&self, other: &LockCell<T>) -> bool {
498-
self.get() == other.get()
499-
}
500-
}
501-
502-
impl<T:Eq + Copy> Eq for LockCell<T> {}
503-
504-
impl<T:PartialOrd + Copy> PartialOrd for LockCell<T> {
505-
#[inline]
506-
fn partial_cmp(&self, other: &LockCell<T>) -> Option<Ordering> {
507-
self.get().partial_cmp(&other.get())
508-
}
509-
510-
#[inline]
511-
fn lt(&self, other: &LockCell<T>) -> bool {
512-
self.get() < other.get()
513-
}
514-
515-
#[inline]
516-
fn le(&self, other: &LockCell<T>) -> bool {
517-
self.get() <= other.get()
518-
}
519-
520-
#[inline]
521-
fn gt(&self, other: &LockCell<T>) -> bool {
522-
self.get() > other.get()
523-
}
524-
525-
#[inline]
526-
fn ge(&self, other: &LockCell<T>) -> bool {
527-
self.get() >= other.get()
528-
}
529-
}
530-
531-
impl<T:Ord + Copy> Ord for LockCell<T> {
532-
#[inline]
533-
fn cmp(&self, other: &LockCell<T>) -> Ordering {
534-
self.get().cmp(&other.get())
535-
}
536-
}
537-
538450
#[derive(Debug)]
539451
pub struct Lock<T>(InnerLock<T>);
540452

0 commit comments

Comments
 (0)