Skip to content

Commit 03b7cec

Browse files
committed
Replace LockCell with atomic types
1 parent 35a64f8 commit 03b7cec

File tree

5 files changed

+100
-175
lines changed

5 files changed

+100
-175
lines changed

src/librustc/session/mod.rs

+29-16
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ use util::common::{duration_to_secs_str, ErrorReported};
1616
use util::common::ProfileQueriesMsg;
1717

1818
use rustc_data_structures::base_n;
19-
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
19+
use rustc_data_structures::sync::{
20+
self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, AtomicBool, Ordering,
21+
Ordering::SeqCst,
22+
};
2023

2124
use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
2225
use errors::emitter::{Emitter, EmitterWriter};
@@ -41,7 +44,6 @@ use std::io::Write;
4144
use std::path::PathBuf;
4245
use std::time::Duration;
4346
use std::sync::mpsc;
44-
use std::sync::atomic::{AtomicUsize, Ordering};
4547

4648
mod code_stats;
4749
pub mod config;
@@ -138,15 +140,15 @@ pub struct Session {
138140
/// If -zfuel=crate=n is specified, Some(crate).
139141
optimization_fuel_crate: Option<String>,
140142
/// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
141-
optimization_fuel_limit: LockCell<u64>,
143+
optimization_fuel_limit: AtomicU64,
142144
/// We're rejecting all further optimizations.
143-
out_of_fuel: LockCell<bool>,
145+
out_of_fuel: AtomicBool,
144146

145147
// The next two are public because the driver needs to read them.
146148
/// If -zprint-fuel=crate, Some(crate).
147149
pub print_fuel_crate: Option<String>,
148150
/// Always set to zero and incremented so that we can print fuel expended by a crate.
149-
pub print_fuel: LockCell<u64>,
151+
pub print_fuel: AtomicU64,
150152

151153
/// Loaded up early on in the initialization of this `Session` to avoid
152154
/// false positives about a job server in our environment.
@@ -857,32 +859,43 @@ impl Session {
857859
self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed));
858860
}
859861

860-
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
861-
/// This expends fuel if applicable, and records fuel if applicable.
862-
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
862+
#[inline(never)]
863+
#[cold]
864+
pub fn consider_optimizing_cold<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
863865
let mut ret = true;
864866
if let Some(ref c) = self.optimization_fuel_crate {
865867
if c == crate_name {
866868
assert_eq!(self.query_threads(), 1);
867-
let fuel = self.optimization_fuel_limit.get();
869+
let fuel = self.optimization_fuel_limit.load(SeqCst);
868870
ret = fuel != 0;
869-
if fuel == 0 && !self.out_of_fuel.get() {
871+
if fuel == 0 && !self.out_of_fuel.load(SeqCst) {
870872
eprintln!("optimization-fuel-exhausted: {}", msg());
871-
self.out_of_fuel.set(true);
873+
self.out_of_fuel.store(true, SeqCst);
872874
} else if fuel > 0 {
873-
self.optimization_fuel_limit.set(fuel - 1);
875+
self.optimization_fuel_limit.store(fuel - 1, SeqCst);
874876
}
875877
}
876878
}
877879
if let Some(ref c) = self.print_fuel_crate {
878880
if c == crate_name {
879881
assert_eq!(self.query_threads(), 1);
880-
self.print_fuel.set(self.print_fuel.get() + 1);
882+
self.print_fuel.store(self.print_fuel.load(SeqCst) + 1, SeqCst);
881883
}
882884
}
883885
ret
884886
}
885887

888+
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
889+
/// This expends fuel if applicable, and records fuel if applicable.
890+
#[inline(always)]
891+
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
892+
if likely!(self.optimization_fuel_crate.is_none() && self.print_fuel_crate.is_none()) {
893+
true
894+
} else {
895+
self.consider_optimizing_cold(crate_name, msg)
896+
}
897+
}
898+
886899
/// Returns the number of query threads that should be used for this
887900
/// compilation
888901
pub fn query_threads_from_opts(opts: &config::Options) -> usize {
@@ -1128,9 +1141,9 @@ pub fn build_session_(
11281141

11291142
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
11301143
let optimization_fuel_limit =
1131-
LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
1144+
AtomicU64::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
11321145
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
1133-
let print_fuel = LockCell::new(0);
1146+
let print_fuel = AtomicU64::new(0);
11341147

11351148
let working_dir = env::current_dir().unwrap_or_else(|e|
11361149
p_s.span_diagnostic
@@ -1195,7 +1208,7 @@ pub fn build_session_(
11951208
optimization_fuel_limit,
11961209
print_fuel_crate,
11971210
print_fuel,
1198-
out_of_fuel: LockCell::new(false),
1211+
out_of_fuel: AtomicBool::new(false),
11991212
// Note that this is unsafe because it may misinterpret file descriptors
12001213
// on Unix as jobserver file descriptors. We hopefully execute this near
12011214
// the beginning of the process though to ensure we don't get false

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#![feature(hash_raw_entry)]
2222
#![feature(stmt_expr_attributes)]
2323
#![feature(core_intrinsics)]
24+
#![feature(integer_atomics)]
2425

2526
#![cfg_attr(unix, feature(libc))]
2627
#![cfg_attr(test, feature(test))]

src/librustc_data_structures/sync.rs

+61-149
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@
1010
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_queries) is true,
1111
//! `RefCell` otherwise.
1212
//!
13-
//! `LockCell` is a thread safe version of `Cell`, with `set` and `get` operations.
14-
//! It can never deadlock. It uses `Cell` when
15-
//! cfg!(parallel_queries) is false, otherwise it is a `Lock`.
16-
//!
1713
//! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
1814
//!
1915
//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise.
@@ -23,11 +19,7 @@
2319
2420
use std::collections::HashMap;
2521
use std::hash::{Hash, BuildHasher};
26-
use std::cmp::Ordering;
2722
use std::marker::PhantomData;
28-
use std::fmt::Debug;
29-
use std::fmt::Formatter;
30-
use std::fmt;
3123
use std::ops::{Deref, DerefMut};
3224
use owning_ref::{Erased, OwningRef};
3325

@@ -54,6 +46,9 @@ pub fn serial_scope<F, R>(f: F) -> R
5446
f(&SerialScope)
5547
}
5648

49+
pub use std::sync::atomic::Ordering::SeqCst;
50+
pub use std::sync::atomic::Ordering;
51+
5752
cfg_if! {
5853
if #[cfg(not(parallel_queries))] {
5954
pub auto trait Send {}
@@ -69,6 +64,62 @@ cfg_if! {
6964
}
7065
}
7166

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

@@ -160,47 +211,6 @@ cfg_if! {
160211
MTLock(self.0.clone())
161212
}
162213
}
163-
164-
pub struct LockCell<T>(Cell<T>);
165-
166-
impl<T> LockCell<T> {
167-
#[inline(always)]
168-
pub fn new(inner: T) -> Self {
169-
LockCell(Cell::new(inner))
170-
}
171-
172-
#[inline(always)]
173-
pub fn into_inner(self) -> T {
174-
self.0.into_inner()
175-
}
176-
177-
#[inline(always)]
178-
pub fn set(&self, new_inner: T) {
179-
self.0.set(new_inner);
180-
}
181-
182-
#[inline(always)]
183-
pub fn get(&self) -> T where T: Copy {
184-
self.0.get()
185-
}
186-
187-
#[inline(always)]
188-
pub fn set_mut(&mut self, new_inner: T) {
189-
self.0.set(new_inner);
190-
}
191-
192-
#[inline(always)]
193-
pub fn get_mut(&mut self) -> T where T: Copy {
194-
self.0.get()
195-
}
196-
}
197-
198-
impl<T> LockCell<Option<T>> {
199-
#[inline(always)]
200-
pub fn take(&self) -> Option<T> {
201-
unsafe { (*self.0.as_ptr()).take() }
202-
}
203-
}
204214
} else {
205215
pub use std::marker::Send as Send;
206216
pub use std::marker::Sync as Sync;
@@ -213,6 +223,8 @@ cfg_if! {
213223
pub use parking_lot::MutexGuard as LockGuard;
214224
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
215225

226+
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
227+
216228
pub use std::sync::Arc as Lrc;
217229
pub use std::sync::Weak as Weak;
218230

@@ -278,47 +290,6 @@ cfg_if! {
278290
v.erase_send_sync_owner()
279291
}}
280292
}
281-
282-
pub struct LockCell<T>(Lock<T>);
283-
284-
impl<T> LockCell<T> {
285-
#[inline(always)]
286-
pub fn new(inner: T) -> Self {
287-
LockCell(Lock::new(inner))
288-
}
289-
290-
#[inline(always)]
291-
pub fn into_inner(self) -> T {
292-
self.0.into_inner()
293-
}
294-
295-
#[inline(always)]
296-
pub fn set(&self, new_inner: T) {
297-
*self.0.lock() = new_inner;
298-
}
299-
300-
#[inline(always)]
301-
pub fn get(&self) -> T where T: Copy {
302-
*self.0.lock()
303-
}
304-
305-
#[inline(always)]
306-
pub fn set_mut(&mut self, new_inner: T) {
307-
*self.0.get_mut() = new_inner;
308-
}
309-
310-
#[inline(always)]
311-
pub fn get_mut(&mut self) -> T where T: Copy {
312-
*self.0.get_mut()
313-
}
314-
}
315-
316-
impl<T> LockCell<Option<T>> {
317-
#[inline(always)]
318-
pub fn take(&self) -> Option<T> {
319-
self.0.lock().take()
320-
}
321-
}
322293
}
323294
}
324295

@@ -466,65 +437,6 @@ impl<T> Once<T> {
466437
}
467438
}
468439

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

0 commit comments

Comments
 (0)