summaryrefslogtreecommitdiff
path: root/rts/sm/GC.c
diff options
context:
space:
mode:
authorGHC GitLab CI <ghc-ci@gitlab-haskell.org>2020-09-18 13:19:34 +0000
committerBen Gamari <ben@smart-cactus.org>2020-10-30 00:41:14 -0400
commita80cc8577774a744d684cd1f513e373405cd2f2b (patch)
treeb99bd0958ae40acdd44621a37a720049614e79cf /rts/sm/GC.c
parent4e4a73868488f83aa9d355d147e116408634c140 (diff)
downloadhaskell-a80cc8577774a744d684cd1f513e373405cd2f2b.tar.gz
rts: Fix race in GC CPU time accounting
Ensure that the GC leader synchronizes with workers before calling stat_endGC.
Diffstat (limited to 'rts/sm/GC.c')
-rw-r--r--rts/sm/GC.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 5e1975076e..d80c0e94c6 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -1278,10 +1278,13 @@ gcWorkerThread (Capability *cap)
// Wait until we're told to continue
RELEASE_SPIN_LOCK(&gct->gc_spin);
- SEQ_CST_STORE(&gct->wakeup, GC_THREAD_WAITING_TO_CONTINUE);
debugTrace(DEBUG_gc, "GC thread %d waiting to continue...",
gct->thread_index);
stat_endGCWorker (cap, gct);
+ // This must come *after* stat_endGCWorker since it serves to
+ // synchronize us with the GC leader, which will later aggregate the
+ // GC statistics.
+ SEQ_CST_STORE(&gct->wakeup, GC_THREAD_WAITING_TO_CONTINUE);
ACQUIRE_SPIN_LOCK(&gct->mut_spin);
debugTrace(DEBUG_gc, "GC thread %d on my way...", gct->thread_index);
@@ -1373,10 +1376,10 @@ wakeup_gc_threads (uint32_t me USED_IF_THREADS,
if (i == me || idle_cap[i]) continue;
inc_running();
debugTrace(DEBUG_gc, "waking up gc thread %d", i);
- if (RELAXED_LOAD(&gc_threads[i]->wakeup) != GC_THREAD_STANDING_BY)
+ if (SEQ_CST_LOAD(&gc_threads[i]->wakeup) != GC_THREAD_STANDING_BY)
barf("wakeup_gc_threads");
- RELAXED_STORE(&gc_threads[i]->wakeup, GC_THREAD_RUNNING);
+ SEQ_CST_STORE(&gc_threads[i]->wakeup, GC_THREAD_RUNNING);
ACQUIRE_SPIN_LOCK(&gc_threads[i]->mut_spin);
RELEASE_SPIN_LOCK(&gc_threads[i]->gc_spin);
}