Skip to content

Commit dd075c9

Browse files
committed
Use rayon thread local values instead of TLS_TCX and fix a deadlock
1 parent 8fd4500 commit dd075c9

File tree

4 files changed

+65
-69
lines changed

4 files changed

+65
-69
lines changed

src/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ graphviz = { path = "../libgraphviz" }
1616
jobserver = "0.1"
1717
log = "0.3"
1818
rayon = { git = "https://github.com/Zoxc/rayon.git", branch = "fiber" }
19-
rayon-core = { git = "https://github.com/Zoxc/rayon.git", branch = "fiber", features=["debug"] }
19+
rayon-core = { git = "https://github.com/Zoxc/rayon.git", branch = "fiber", features=["debug", "tlv"] }
2020
scoped-tls = { git = "https://github.com/Zoxc/scoped-tls.git", features=["nightly"] }
2121
owning_ref = { git = "https://github.com/Zoxc/owning-ref-rs.git" }
2222
rustc_back = { path = "../librustc_back" }

src/librustc/ty/context.rs

Lines changed: 24 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,12 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
13641364
where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
13651365
{
13661366
let interners = CtxtInterners::new(arena);
1367-
tls::enter(self, &interners, query, f)
1367+
let tcx = TyCtxt {
1368+
gcx: self,
1369+
interners: &interners,
1370+
query,
1371+
};
1372+
tls::enter(tcx, f)
13681373
}
13691374
}
13701375

@@ -1511,26 +1516,13 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
15111516
}
15121517

15131518
pub mod tls {
1514-
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
1519+
use super::{GlobalCtxt, TyCtxt};
15151520

1516-
use std::cell::Cell;
15171521
use std::fmt;
15181522
use syntax_pos;
15191523
use ty::maps;
15201524
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
1521-
1522-
/// Marker types used for the scoped TLS slot.
1523-
/// The type context cannot be used directly because the scoped TLS
1524-
/// in libstd doesn't allow types generic over lifetimes.
1525-
enum ThreadLocalGlobalCtxt {}
1526-
enum ThreadLocalInterners {}
1527-
enum ThreadLocalQuery {}
1528-
1529-
thread_local! {
1530-
static TLS_TCX: Cell<Option<(*const ThreadLocalGlobalCtxt,
1531-
*const ThreadLocalInterners,
1532-
*const ThreadLocalQuery)>> = Cell::new(None)
1533-
}
1525+
use rayon_core;
15341526

15351527
fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result {
15361528
with(|tcx| {
@@ -1558,7 +1550,12 @@ pub mod tls {
15581550
current.set(track_diagnostic);
15591551

15601552
let global_query = maps::QueryJob::new(Vec::new(), false, false);
1561-
let result = enter(&gcx, &gcx.global_interners, &global_query, f);
1553+
let tcx = TyCtxt {
1554+
gcx,
1555+
interners: &gcx.global_interners,
1556+
query: &global_query,
1557+
};
1558+
let result = enter(tcx, f);
15621559
current.set(original);
15631560
result
15641561
});
@@ -1568,52 +1565,31 @@ pub mod tls {
15681565
})
15691566
}
15701567

1571-
pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>,
1572-
interners: &'a CtxtInterners<'tcx>,
1573-
query: &'a maps::QueryJob<'gcx>,
1568+
pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
15741569
f: F) -> R
15751570
where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
15761571
{
1577-
let tls_query = maps::QueryJob::new(Vec::new(), false, true);
1578-
let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt;
1579-
let interners_ptr = interners as *const _ as *const ThreadLocalInterners;
1580-
let query_ptr = &tls_query as *const _ as *const ThreadLocalQuery;
1581-
TLS_TCX.with(|tls| {
1582-
let prev = tls.get();
1583-
tls.set(Some((gcx_ptr, interners_ptr, query_ptr)));
1584-
let ret = f(TyCtxt {
1585-
gcx,
1586-
interners,
1587-
query,
1588-
});
1589-
tls.set(prev);
1590-
ret
1572+
rayon_core::fiber::tlv::set(&tcx as *const _ as usize, || {
1573+
f(tcx)
15911574
})
15921575
}
15931576

15941577
pub fn with<F, R>(f: F) -> R
15951578
where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
15961579
{
1597-
TLS_TCX.with(|tcx| {
1598-
let (gcx, interners, query) = tcx.get().unwrap();
1599-
let gcx = unsafe { &*(gcx as *const GlobalCtxt) };
1600-
let interners = unsafe { &*(interners as *const CtxtInterners) };
1601-
let query = unsafe { &*(query as *const maps::QueryJob) };
1602-
f(TyCtxt {
1603-
gcx,
1604-
interners,
1605-
query,
1606-
})
1607-
})
1580+
let tcx = rayon_core::fiber::tlv::get();
1581+
assert!(tcx != 0);
1582+
unsafe { f(*(tcx as *const TyCtxt)) }
16081583
}
16091584

16101585
pub fn with_opt<F, R>(f: F) -> R
16111586
where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R
16121587
{
1613-
if TLS_TCX.with(|tcx| tcx.get().is_some()) {
1614-
with(|v| f(Some(v)))
1615-
} else {
1588+
let tcx = rayon_core::fiber::tlv::get();
1589+
if tcx == 0 {
16161590
f(None)
1591+
} else {
1592+
unsafe { f(Some(*(tcx as *const TyCtxt))) }
16171593
}
16181594
}
16191595
}

src/librustc/ty/maps/plumbing.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
9898
})
9999
}
100100

101+
pub(super) fn cycle_check(self, span: Span, query: &Query<'gcx>) -> Result<(), CycleError<'gcx>>
102+
{
103+
if let Some((i, _)) = self.query().stack.iter().enumerate().rev()
104+
.find(|&(_, &(_, ref q))| q == query) {
105+
Err(CycleError {
106+
span,
107+
cycle: self.query().stack[i..].iter().cloned().collect(),
108+
})
109+
} else {
110+
Ok(())
111+
}
112+
}
113+
101114
/// Try to read a node index for the node dep_node.
102115
/// A node will have an index, when it's already been marked green, or when we can mark it
103116
/// green. This function will mark the current task as a reader of the specified node, when
@@ -167,8 +180,8 @@ macro_rules! define_maps {
167180
use rustc_data_structures::sync::{Lock, LockGuard};
168181
use std::iter;
169182
use errors::Diagnostic;
170-
use std::sync::atomic::Ordering;
171183
use ty::maps::plumbing::QUERY_DEPTH;
184+
use std::sync::atomic::Ordering;
172185

173186
define_map_struct! {
174187
tcx: $tcx,
@@ -258,7 +271,7 @@ macro_rules! define_maps {
258271
QueryMsg::$name(profq_key!(tcx, key))
259272
)
260273
);
261-
/*
274+
262275
loop {
263276
let job = if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
264277
match *value {
@@ -272,10 +285,25 @@ macro_rules! define_maps {
272285
} else {
273286
break
274287
};
275-
assert!(!tcx.query().tls);
276-
job.await();
277-
}*/
288+
lazy_static! {
289+
static ref LOG: bool = ::std::env::var("QUERY_LOG").is_ok();
290+
}
291+
292+
if *LOG {
293+
println!("({}) waiting on query {:?} latch {:x}",
294+
QUERY_DEPTH.load(Ordering::SeqCst),
295+
Query::$name(Clone::clone(&key)), &job.latch as *const _ as usize);
296+
for i in tcx.query().stack.iter() {
297+
println!(" query stack entry {:?}", i);
278298

299+
}
300+
}
301+
// If there is a cycle, waiting will never complete
302+
tcx.cycle_check(span, &Query::$name(Clone::clone(&key)))?;
303+
job.await();
304+
}
305+
/*
306+
use std::sync::atomic::Ordering;
279307
#[allow(warnings)]
280308
loop {
281309
let job = if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
@@ -304,7 +332,7 @@ macro_rules! define_maps {
304332
};
305333
//job.await();
306334
}
307-
335+
*/
308336
// FIXME(eddyb) Get more valid Span's on queries.
309337
// def_span guard is necessary to prevent a recursive loop,
310338
// default_span calls def_span query internally.
@@ -403,24 +431,14 @@ macro_rules! define_maps {
403431
-> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), CycleError<$tcx>>
404432
where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R
405433
{
406-
assert!(!tcx.query().tls);
407-
408434
let query = Query::$name(Clone::clone(&key));
409435

410-
if let Some((i, _)) = tcx.query().stack.iter().enumerate().rev()
411-
.find(|&(_, &(_, ref q))| *q == query) {
412-
return Err(CycleError {
413-
span,
414-
cycle: tcx.query().stack.iter().step_by(i).cloned().collect(),
415-
});
416-
}
436+
tcx.cycle_check(span, &query)?;
417437

418438
lazy_static! {
419439
static ref LOG: bool = ::std::env::var("QUERY_LOG").is_ok();
420440
}
421441

422-
use std::sync::atomic::Ordering;
423-
424442
let entry = (span, query);
425443
let stack = tcx.query().stack.iter().cloned().chain(iter::once(entry)).collect();
426444
let job = Lrc::new(QueryJob::new(stack, true, false));
@@ -447,7 +465,9 @@ macro_rules! define_maps {
447465
.or_insert(QueryResult::Started(job.clone()));
448466
}
449467

450-
let r = compute(tcx.with_query(&*job));
468+
let r = ty::tls::enter(tcx.with_query(&*job), |new_tcx| {
469+
compute(new_tcx)
470+
});
451471

452472
if *LOG {
453473
println!("ending query {:?}", query.clone());

0 commit comments

Comments
 (0)