@@ -94,15 +94,15 @@ impl<'tcx> QueryJob<'tcx> {
94
94
#[ cfg( parallel_queries) ]
95
95
{
96
96
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 ( ) ,
99
99
span,
100
- cycle : None ,
100
+ cycle : Lock :: new ( None ) ,
101
101
condvar : Condvar :: new ( ) ,
102
- } ;
103
- self . latch . await ( & mut waiter) ;
102
+ } ) ;
103
+ self . latch . await ( & waiter) ;
104
104
105
- match waiter. cycle {
105
+ match Lrc :: get_mut ( & mut waiter) . unwrap ( ) . cycle . get_mut ( ) . take ( ) {
106
106
None => Ok ( ( ) ) ,
107
107
Some ( cycle) => Err ( cycle)
108
108
}
@@ -154,10 +154,10 @@ impl<'tcx> QueryJob<'tcx> {
154
154
155
155
#[ cfg( parallel_queries) ]
156
156
struct QueryWaiter < ' tcx > {
157
- query : * const Option < Lrc < QueryJob < ' tcx > > > ,
157
+ query : Option < Lrc < QueryJob < ' tcx > > > ,
158
158
condvar : Condvar ,
159
159
span : Span ,
160
- cycle : Option < CycleError < ' tcx > > ,
160
+ cycle : Lock < Option < CycleError < ' tcx > > > ,
161
161
}
162
162
163
163
#[ cfg( parallel_queries) ]
@@ -171,13 +171,9 @@ impl<'tcx> QueryWaiter<'tcx> {
171
171
#[ cfg( parallel_queries) ]
172
172
struct QueryLatchInfo < ' tcx > {
173
173
complete : bool ,
174
- waiters : Vec < * mut QueryWaiter < ' tcx > > ,
174
+ waiters : Vec < Lrc < QueryWaiter < ' tcx > > > ,
175
175
}
176
176
177
- // Required because of raw pointers
178
- #[ cfg( parallel_queries) ]
179
- unsafe impl < ' tcx > Send for QueryLatchInfo < ' tcx > { }
180
-
181
177
#[ cfg( parallel_queries) ]
182
178
struct QueryLatch < ' tcx > {
183
179
info : Mutex < QueryLatchInfo < ' tcx > > ,
@@ -195,14 +191,14 @@ impl<'tcx> QueryLatch<'tcx> {
195
191
}
196
192
197
193
/// 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 > > ) {
199
195
let mut info = self . info . lock ( ) ;
200
196
if !info. complete {
201
197
// We push the waiter on to the `waiters` list. It can be accessed inside
202
198
// the `wait` call below, by 1) the `set` method or 2) by deadlock detection.
203
199
// Both of these will remove it from the `waiters` list before resuming
204
200
// this thread.
205
- info. waiters . push ( waiter) ;
201
+ info. waiters . push ( waiter. clone ( ) ) ;
206
202
207
203
// If this detects a deadlock and the deadlock handler want to resume this thread
208
204
// we have to be in the `wait` call. This is ensured by the deadlock handler
@@ -219,9 +215,7 @@ impl<'tcx> QueryLatch<'tcx> {
219
215
info. complete = true ;
220
216
let registry = rayon_core:: Registry :: current ( ) ;
221
217
for waiter in info. waiters . drain ( ..) {
222
- unsafe {
223
- ( * waiter) . notify ( & registry) ;
224
- }
218
+ waiter. notify ( & registry) ;
225
219
}
226
220
}
227
221
@@ -230,7 +224,7 @@ impl<'tcx> QueryLatch<'tcx> {
230
224
fn extract_waiter (
231
225
& self ,
232
226
waiter : usize ,
233
- ) -> * mut QueryWaiter < ' tcx > {
227
+ ) -> Lrc < QueryWaiter < ' tcx > > {
234
228
let mut info = self . info . lock ( ) ;
235
229
debug_assert ! ( !info. complete) ;
236
230
// Remove the waiter from the list of waiters
@@ -270,13 +264,11 @@ where
270
264
}
271
265
272
266
// 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) ) ) ;
280
272
}
281
273
}
282
274
}
@@ -359,7 +351,7 @@ fn connected_to_root<'tcx>(query: Ref<'tcx>, visited: &mut HashSet<Ref<'tcx>>) -
359
351
#[ cfg( parallel_queries) ]
360
352
fn remove_cycle < ' tcx > (
361
353
jobs : & mut Vec < Ref < ' tcx > > ,
362
- wakelist : & mut Vec < * mut QueryWaiter < ' tcx > > ,
354
+ wakelist : & mut Vec < Lrc < QueryWaiter < ' tcx > > > ,
363
355
tcx : TyCtxt < ' _ , ' tcx , ' _ >
364
356
) -> bool {
365
357
let mut visited = HashSet :: new ( ) ;
@@ -439,9 +431,9 @@ fn remove_cycle<'tcx>(
439
431
// Extract the waiter we want to resume
440
432
let waiter = waitee_query. latch . extract_waiter ( waiter_idx) ;
441
433
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
443
435
unsafe {
444
- ( * waiter) . cycle = Some ( error) ;
436
+ * waiter. cycle . lock ( ) = Some ( error) ;
445
437
}
446
438
447
439
// Put the waiter on the list of things to resume
@@ -525,9 +517,7 @@ fn deadlock(tcx: TyCtxt<'_, '_, '_>, registry: &rayon_core::Registry) {
525
517
526
518
// FIXME: Ensure this won't cause a deadlock before we return
527
519
for waiter in wakelist. into_iter ( ) {
528
- unsafe {
529
- ( * waiter) . notify ( registry) ;
530
- }
520
+ waiter. notify ( registry) ;
531
521
}
532
522
533
523
on_panic. disable ( ) ;
0 commit comments