summaryrefslogtreecommitdiff
path: root/rts/sm
diff options
context:
space:
mode:
authorAndreas Klebinger <klebinger.andreas@gmx.at>2022-11-29 12:19:16 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2023-01-12 15:52:23 -0500
commita1491c8791c57a64d94bc08d639d585815c8d4e2 (patch)
tree2798061cf74e3ea784939f4da456fd8af3200857 /rts/sm
parent905d0b6e1db714b306a940fb58a570c9294aa88d (diff)
downloadhaskell-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.c21
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