summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGHC GitLab CI <ghc-ci@gitlab-haskell.org>2020-12-07 21:43:31 +0000
committerGHC GitLab CI <ghc-ci@gitlab-haskell.org>2020-12-10 04:29:25 +0000
commit13b6696babb2acbd19d18552c9a52cf75cf47d2e (patch)
treee1e02fa3172b117781c10d6522b2ddf448c95767
parent4123b929e477d333290c958628d70240c4bd7521 (diff)
downloadhaskell-13b6696babb2acbd19d18552c9a52cf75cf47d2e.tar.gz
nonmoving: Ensure deadlock detection promotion works
Previously the deadlock-detection promotion logic in alloc_for_copy was just plain wrong: it failed to fire when gct->evac_gen_no != oldest_gen->gen_no. The fix is simple: move the
-rw-r--r--rts/sm/Evac.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/rts/sm/Evac.c b/rts/sm/Evac.c
index a4cbd6e6b3..ca43f57db9 100644
--- a/rts/sm/Evac.c
+++ b/rts/sm/Evac.c
@@ -73,24 +73,14 @@ alloc_for_copy (uint32_t size, uint32_t gen_no)
StgPtr to;
gen_workspace *ws;
- /* Find out where we're going, using the handy "to" pointer in
- * the gen of the source object. If it turns out we need to
- * evacuate to an older generation, adjust it here (see comment
- * by evacuate()).
- */
- if (gen_no < gct->evac_gen_no) {
- if (gct->eager_promotion) {
- gen_no = gct->evac_gen_no;
- } else if (RTS_UNLIKELY(RtsFlags.GcFlags.useNonmoving) && deadlock_detect_gc) {
- /* See Note [Deadlock detection under nonmoving collector]. */
- gen_no = oldest_gen->no;
- } else {
- gct->failed_to_evac = true;
+ if (RTS_UNLIKELY(RtsFlags.GcFlags.useNonmoving)) {
+ /* See Note [Deadlock detection under nonmoving collector]. */
+ const uint32_t oldest_gen_no = oldest_gen->no;
+ if (deadlock_detect_gc) {
+ gen_no = oldest_gen_no;
}
- }
- if (RTS_UNLIKELY(RtsFlags.GcFlags.useNonmoving)) {
- if (gen_no == oldest_gen->no) {
+ if (gen_no == oldest_gen_no) {
gct->copied += size;
to = nonmovingAllocate(gct->cap, size);
@@ -98,7 +88,7 @@ alloc_for_copy (uint32_t size, uint32_t gen_no)
// current->todo_link == NULL means not in todo list
struct NonmovingSegment *seg = nonmovingGetSegment(to);
if (!seg->todo_link) {
- gen_workspace *ws = &gct->gens[oldest_gen->no];
+ gen_workspace *ws = &gct->gens[oldest_gen_no];
seg->todo_link = ws->todo_seg;
ws->todo_seg = seg;
}
@@ -111,12 +101,26 @@ alloc_for_copy (uint32_t size, uint32_t gen_no)
// so there is no need.
//
// See Note [Non-moving GC: Marking evacuated objects].
- if (major_gc && !deadlock_detect_gc)
+ if (major_gc && !deadlock_detect_gc) {
markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, (StgClosure *) to);
+ }
return to;
}
}
+ /* Find out where we're going, using the handy "to" pointer in
+ * the gen of the source object. If it turns out we need to
+ * evacuate to an older generation, adjust it here (see comment
+ * by evacuate()).
+ */
+ if (gen_no < gct->evac_gen_no) {
+ if (gct->eager_promotion) {
+ gen_no = gct->evac_gen_no;
+ } else {
+ gct->failed_to_evac = true;
+ }
+ }
+
ws = &gct->gens[gen_no]; // zero memory references here
/* chain a new block onto the to-space for the destination gen if