Skip to content

Commit b2555bd

Browse files
committed
Make QueryWaiter use safe code
1 parent 3571684 commit b2555bd

File tree

1 file changed

+22
-32
lines changed

1 file changed

+22
-32
lines changed

src/librustc/ty/maps/job.rs

+22-32
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,15 @@ impl<'tcx> QueryJob<'tcx> {
9494
#[cfg(parallel_queries)]
9595
{
9696
tls::with_related_context(tcx, move |icx| {
97-
let mut waiter = QueryWaiter {
98-
query: &icx.query,
97+
let mut waiter = Lrc::new(QueryWaiter {
98+
query: icx.query.clone(),
9999
span,
100-
cycle: None,
100+
cycle: Lock::new(None),
101101
condvar: Condvar::new(),
102-
};
103-
self.latch.await(&mut waiter);
102+
});
103+
self.latch.await(&waiter);
104104

105-
match waiter.cycle {
105+
match Lrc::get_mut(&mut waiter).unwrap().cycle.get_mut().take() {
106106
None => Ok(()),
107107
Some(cycle) => Err(cycle)
108108
}
@@ -154,10 +154,10 @@ impl<'tcx> QueryJob<'tcx> {
154154

155155
#[cfg(parallel_queries)]
156156
struct QueryWaiter<'tcx> {
157-
query: *const Option<Lrc<QueryJob<'tcx>>>,
157+
query: Option<Lrc<QueryJob<'tcx>>>,
158158
condvar: Condvar,
159159
span: Span,
160-
cycle: Option<CycleError<'tcx>>,
160+
cycle: Lock<Option<CycleError<'tcx>>>,
161161
}
162162

163163
#[cfg(parallel_queries)]
@@ -171,13 +171,9 @@ impl<'tcx> QueryWaiter<'tcx> {
171171
#[cfg(parallel_queries)]
172172
struct QueryLatchInfo<'tcx> {
173173
complete: bool,
174-
waiters: Vec<*mut QueryWaiter<'tcx>>,
174+
waiters: Vec<Lrc<QueryWaiter<'tcx>>>,
175175
}
176176

177-
// Required because of raw pointers
178-
#[cfg(parallel_queries)]
179-
unsafe impl<'tcx> Send for QueryLatchInfo<'tcx> {}
180-
181177
#[cfg(parallel_queries)]
182178
struct QueryLatch<'tcx> {
183179
info: Mutex<QueryLatchInfo<'tcx>>,
@@ -195,14 +191,14 @@ impl<'tcx> QueryLatch<'tcx> {
195191
}
196192

197193
/// Awaits the caller on this latch by blocking the current thread.
198-
fn await(&self, waiter: &mut QueryWaiter<'tcx>) {
194+
fn await(&self, waiter: &Lrc<QueryWaiter<'tcx>>) {
199195
let mut info = self.info.lock();
200196
if !info.complete {
201197
// We push the waiter on to the `waiters` list. It can be accessed inside
202198
// the `wait` call below, by 1) the `set` method or 2) by deadlock detection.
203199
// Both of these will remove it from the `waiters` list before resuming
204200
// this thread.
205-
info.waiters.push(waiter);
201+
info.waiters.push(waiter.clone());
206202

207203
// If this detects a deadlock and the deadlock handler want to resume this thread
208204
// we have to be in the `wait` call. This is ensured by the deadlock handler
@@ -219,9 +215,7 @@ impl<'tcx> QueryLatch<'tcx> {
219215
info.complete = true;
220216
let registry = rayon_core::Registry::current();
221217
for waiter in info.waiters.drain(..) {
222-
unsafe {
223-
(*waiter).notify(&registry);
224-
}
218+
waiter.notify(&registry);
225219
}
226220
}
227221

@@ -230,7 +224,7 @@ impl<'tcx> QueryLatch<'tcx> {
230224
fn extract_waiter(
231225
&self,
232226
waiter: usize,
233-
) -> *mut QueryWaiter<'tcx> {
227+
) -> Lrc<QueryWaiter<'tcx>> {
234228
let mut info = self.info.lock();
235229
debug_assert!(!info.complete);
236230
// Remove the waiter from the list of waiters
@@ -270,13 +264,11 @@ where
270264
}
271265

272266
// Visit the explict waiters which use condvars and are resumable
273-
for (i, &waiter) in query.latch.info.lock().waiters.iter().enumerate() {
274-
unsafe {
275-
if let Some(ref waiter_query) = *(*waiter).query {
276-
if visit((*waiter).span, &**waiter_query as Ref).is_some() {
277-
// Return a value which indicates that this waiter can be resumed
278-
return Some(Some((query_ref, i)));
279-
}
267+
for (i, waiter) in query.latch.info.lock().waiters.iter().enumerate() {
268+
if let Some(ref waiter_query) = waiter.query {
269+
if visit(waiter.span, &**waiter_query).is_some() {
270+
// Return a value which indicates that this waiter can be resumed
271+
return Some(Some((query_ref, i)));
280272
}
281273
}
282274
}
@@ -359,7 +351,7 @@ fn connected_to_root<'tcx>(query: Ref<'tcx>, visited: &mut HashSet<Ref<'tcx>>) -
359351
#[cfg(parallel_queries)]
360352
fn remove_cycle<'tcx>(
361353
jobs: &mut Vec<Ref<'tcx>>,
362-
wakelist: &mut Vec<*mut QueryWaiter<'tcx>>,
354+
wakelist: &mut Vec<Lrc<QueryWaiter<'tcx>>>,
363355
tcx: TyCtxt<'_, 'tcx, '_>
364356
) -> bool {
365357
let mut visited = HashSet::new();
@@ -439,9 +431,9 @@ fn remove_cycle<'tcx>(
439431
// Extract the waiter we want to resume
440432
let waiter = waitee_query.latch.extract_waiter(waiter_idx);
441433

442-
// Set the cycle error it will be picked it up when resumed
434+
// Set the cycle error so it will be picked up when resumed
443435
unsafe {
444-
(*waiter).cycle = Some(error);
436+
*waiter.cycle.lock() = Some(error);
445437
}
446438

447439
// Put the waiter on the list of things to resume
@@ -525,9 +517,7 @@ fn deadlock(tcx: TyCtxt<'_, '_, '_>, registry: &rayon_core::Registry) {
525517

526518
// FIXME: Ensure this won't cause a deadlock before we return
527519
for waiter in wakelist.into_iter() {
528-
unsafe {
529-
(*waiter).notify(registry);
530-
}
520+
waiter.notify(registry);
531521
}
532522

533523
on_panic.disable();

0 commit comments

Comments
 (0)