diff options
author | Andreas Klebinger <klebinger.andreas@gmx.at> | 2022-11-29 12:19:16 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2023-01-12 15:52:23 -0500 |
commit | a1491c8791c57a64d94bc08d639d585815c8d4e2 (patch) | |
tree | 2798061cf74e3ea784939f4da456fd8af3200857 /rts/sm | |
parent | 905d0b6e1db714b306a940fb58a570c9294aa88d (diff) | |
download | haskell-a1491c8791c57a64d94bc08d639d585815c8d4e2.tar.gz |
Only gc sparks locally when we can ensure marking is done.
When performing GC without work stealing there was no guarantee that
spark pruning was happening after marking of the sparks. This could
cause us to GC live sparks under certain circumstances.
Fixes #22528.
Diffstat (limited to 'rts/sm')
-rw-r--r-- | rts/sm/GC.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c index 5bfee440a3..2438ad2816 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -292,6 +292,7 @@ GarbageCollect (uint32_t collect_gen, any_work, scav_find_work, max_n_todo_overflow; #if defined(THREADED_RTS) gc_thread *saved_gct; + bool gc_sparks_all_caps; #endif uint32_t g, n; // The time we should report our heap census as occurring at, if necessary. @@ -559,6 +560,9 @@ GarbageCollect (uint32_t collect_gen, StgTSO *resurrected_threads = END_TSO_QUEUE; // must be last... invariant is that everything is fully // scavenged at this point. +#if defined(THREADED_RTS) + gc_sparks_all_caps = !work_stealing || !is_par_gc(); +#endif work_stealing = false; while (traverseWeakPtrList(&dead_weak_ptr_list, &resurrected_threads)) { @@ -571,8 +575,9 @@ GarbageCollect (uint32_t collect_gen, gcStableNameTable(); #if defined(THREADED_RTS) - if (!is_par_gc()) { - for (n = 0; n < getNumCapabilities(); n++) { + // See Note [Pruning the spark pool] + if(gc_sparks_all_caps) { + for (n = 0; n < n_capabilities; n++) { pruneSparkQueue(false, getCapability(n)); } } else { @@ -1379,7 +1384,6 @@ void gcWorkerThread (Capability *cap) { gc_thread *saved_gct; - // necessary if we stole a callee-saves register for gct: saved_gct = gct; @@ -1410,13 +1414,10 @@ gcWorkerThread (Capability *cap) scavenge_until_all_done(); #if defined(THREADED_RTS) - // Now that the whole heap is marked, we discard any sparks that - // were found to be unreachable. The main GC thread is currently - // marking heap reachable via weak pointers, so it is - // non-deterministic whether a spark will be retained if it is - // only reachable via weak pointers. To fix this problem would - // require another GC barrier, which is too high a price. - pruneSparkQueue(false, cap); + // See Note [Pruning the spark pool] + if(work_stealing && is_par_gc()) { + pruneSparkQueue(false, cap); + } #endif // Wait until we're told to continue |