| ... |
... |
@@ -15,6 +15,7 @@ |
|
15
|
15
|
#include "RaiseAsync.h"
|
|
16
|
16
|
#include "Trace.h"
|
|
17
|
17
|
#include "Threads.h"
|
|
|
18
|
+#include "Messages.h"
|
|
18
|
19
|
#include "sm/NonMovingMark.h"
|
|
19
|
20
|
|
|
20
|
21
|
#include <string.h> // for memmove()
|
| ... |
... |
@@ -314,52 +315,66 @@ threadPaused(Capability *cap, StgTSO *tso) |
|
314
|
315
|
continue;
|
|
315
|
316
|
}
|
|
316
|
317
|
|
|
317
|
|
- // an EAGER_BLACKHOLE or CAF_BLACKHOLE gets turned into a
|
|
318
|
|
- // BLACKHOLE here.
|
|
|
318
|
+ // If we have a frame that is already eagerly blackholed, we
|
|
|
319
|
+ // shouldn't overwrite its payload: There may already be a blocking
|
|
|
320
|
+ // queue (see #26324).
|
|
|
321
|
+ if(frame_info == &stg_bh_upd_frame_info) {
|
|
|
322
|
+ // eager black hole: we do nothing
|
|
|
323
|
+
|
|
|
324
|
+ // it should be a black hole that we own
|
|
|
325
|
+ ASSERT(bh_info == &stg_BLACKHOLE_info ||
|
|
|
326
|
+ bh_info == &__stg_EAGER_BLACKHOLE_info ||
|
|
|
327
|
+ bh_info == &stg_CAF_BLACKHOLE_info);
|
|
|
328
|
+ ASSERT(blackHoleOwner(bh) == tso || blackHoleOwner(bh) == NULL);
|
|
|
329
|
+ } else {
|
|
|
330
|
+ // lazy black hole
|
|
|
331
|
+
|
|
319
|
332
|
#if defined(THREADED_RTS)
|
|
320
|
|
- // first we turn it into a WHITEHOLE to claim it, and if
|
|
321
|
|
- // successful we write our TSO and then the BLACKHOLE info pointer.
|
|
322
|
|
- cur_bh_info = (const StgInfoTable *)
|
|
323
|
|
- cas((StgVolatilePtr)&bh->header.info,
|
|
324
|
|
- (StgWord)bh_info,
|
|
325
|
|
- (StgWord)&stg_WHITEHOLE_info);
|
|
326
|
|
-
|
|
327
|
|
- if (cur_bh_info != bh_info) {
|
|
328
|
|
- bh_info = cur_bh_info;
|
|
|
333
|
+ // first we turn it into a WHITEHOLE to claim it, and if
|
|
|
334
|
+ // successful we write our TSO and then the BLACKHOLE info pointer.
|
|
|
335
|
+ cur_bh_info = (const StgInfoTable *)
|
|
|
336
|
+ cas((StgVolatilePtr)&bh->header.info,
|
|
|
337
|
+ (StgWord)bh_info,
|
|
|
338
|
+ (StgWord)&stg_WHITEHOLE_info);
|
|
|
339
|
+
|
|
|
340
|
+ if (cur_bh_info != bh_info) {
|
|
|
341
|
+ bh_info = cur_bh_info;
|
|
329
|
342
|
#if defined(PROF_SPIN)
|
|
330
|
|
- NONATOMIC_ADD(&whitehole_threadPaused_spin, 1);
|
|
|
343
|
+ NONATOMIC_ADD(&whitehole_threadPaused_spin, 1);
|
|
331
|
344
|
#endif
|
|
332
|
|
- busy_wait_nop();
|
|
333
|
|
- goto retry;
|
|
334
|
|
- }
|
|
|
345
|
+ busy_wait_nop();
|
|
|
346
|
+ goto retry;
|
|
|
347
|
+ }
|
|
335
|
348
|
#endif
|
|
336
|
|
-
|
|
337
|
|
- IF_NONMOVING_WRITE_BARRIER_ENABLED {
|
|
338
|
|
- if (ip_THUNK(INFO_PTR_TO_STRUCT(bh_info))) {
|
|
339
|
|
- // We are about to replace a thunk with a blackhole.
|
|
340
|
|
- // Add the free variables of the closure we are about to
|
|
341
|
|
- // overwrite to the update remembered set.
|
|
342
|
|
- // N.B. We caught the WHITEHOLE case above.
|
|
343
|
|
- updateRemembSetPushThunkEager(cap,
|
|
344
|
|
- THUNK_INFO_PTR_TO_STRUCT(bh_info),
|
|
345
|
|
- (StgThunk *) bh);
|
|
|
349
|
+ ASSERT(bh_info != &stg_WHITEHOLE_info);
|
|
|
350
|
+
|
|
|
351
|
+ IF_NONMOVING_WRITE_BARRIER_ENABLED {
|
|
|
352
|
+ if (ip_THUNK(INFO_PTR_TO_STRUCT(bh_info))) {
|
|
|
353
|
+ // We are about to replace a thunk with a blackhole.
|
|
|
354
|
+ // Add the free variables of the closure we are about to
|
|
|
355
|
+ // overwrite to the update remembered set.
|
|
|
356
|
+ // N.B. We caught the WHITEHOLE case above.
|
|
|
357
|
+ updateRemembSetPushThunkEager(cap,
|
|
|
358
|
+ THUNK_INFO_PTR_TO_STRUCT(bh_info),
|
|
|
359
|
+ (StgThunk *) bh);
|
|
|
360
|
+ }
|
|
346
|
361
|
}
|
|
347
|
|
- }
|
|
348
|
362
|
|
|
349
|
|
- // zero out the slop so that the sanity checker can tell
|
|
350
|
|
- // where the next closure is. N.B. We mustn't do this until we have
|
|
351
|
|
- // pushed the free variables to the update remembered set above.
|
|
352
|
|
- OVERWRITING_CLOSURE_SIZE(bh, closure_sizeW_(bh, INFO_PTR_TO_STRUCT(bh_info)));
|
|
|
363
|
+ // zero out the slop so that the sanity checker can tell
|
|
|
364
|
+ // where the next closure is. N.B. We mustn't do this until we have
|
|
|
365
|
+ // pushed the free variables to the update remembered set above.
|
|
|
366
|
+ OVERWRITING_CLOSURE_SIZE(bh, closure_sizeW_(bh, INFO_PTR_TO_STRUCT(bh_info)));
|
|
353
|
367
|
|
|
354
|
|
- // The payload of the BLACKHOLE points to the TSO
|
|
355
|
|
- RELEASE_STORE(&((StgInd *)bh)->indirectee, (StgClosure *)tso);
|
|
356
|
|
- SET_INFO_RELEASE(bh,&stg_BLACKHOLE_info);
|
|
|
368
|
+ // The payload of the BLACKHOLE points to the TSO
|
|
|
369
|
+ RELEASE_STORE(&((StgInd *)bh)->indirectee, (StgClosure *)tso);
|
|
|
370
|
+ SET_INFO_RELEASE(bh,&stg_BLACKHOLE_info);
|
|
357
|
371
|
|
|
358
|
|
- // .. and we need a write barrier, since we just mutated the closure:
|
|
359
|
|
- recordClosureMutated(cap,bh);
|
|
|
372
|
+ // .. and we need a write barrier, since we just mutated the closure:
|
|
|
373
|
+ recordClosureMutated(cap,bh);
|
|
360
|
374
|
|
|
361
|
|
- // We pretend that bh has just been created.
|
|
362
|
|
- LDV_RECORD_CREATE(bh);
|
|
|
375
|
+ // We pretend that bh has just been created.
|
|
|
376
|
+ LDV_RECORD_CREATE(bh);
|
|
|
377
|
+ }
|
|
363
|
378
|
|
|
364
|
379
|
frame = (StgClosure *) ((StgUpdateFrame *)frame + 1);
|
|
365
|
380
|
if (prev_was_update_frame) {
|