summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2015-07-15 13:07:35 +0100
committerSimon Marlow <marlowsd@gmail.com>2015-07-15 14:59:28 +0100
commit75fd5dc204fb6bb9014f6bba4d680facbc952faf (patch)
treee66ef6e29165eca3ac259a2645f2405a6780e5fe /rts
parenta592e9ffcfb288cd154bad60dc8003b781355533 (diff)
downloadhaskell-75fd5dc204fb6bb9014f6bba4d680facbc952faf.tar.gz
Don't get a new nursery if we exceeded large_alloc_lim
Summary: When using nursery chunks, if we failed a heap check due to large_alloc_lim, we would pointlessly keep grabbing new nursery chunks when we should just GC immediately. Test Plan: validate Reviewers: austin, bgamari, niteria Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D1072
Diffstat (limited to 'rts')
-rw-r--r--rts/Schedule.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c
index f1e95bfbfa..257e39abaa 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -1084,6 +1084,17 @@ schedulePostRunThread (Capability *cap, StgTSO *t)
static rtsBool
scheduleHandleHeapOverflow( Capability *cap, StgTSO *t )
{
+ if (cap->r.rHpLim == NULL || cap->context_switch) {
+ // Sometimes we miss a context switch, e.g. when calling
+ // primitives in a tight loop, MAYBE_GC() doesn't check the
+ // context switch flag, and we end up waiting for a GC.
+ // See #1984, and concurrent/should_run/1984
+ cap->context_switch = 0;
+ appendToRunQueue(cap,t);
+ } else {
+ pushOnRunQueue(cap,t);
+ }
+
// did the task ask for a large block?
if (cap->r.rHpAlloc > BLOCK_SIZE) {
// if so, get one and push it on the front of the nursery.
@@ -1141,27 +1152,23 @@ scheduleHandleHeapOverflow( Capability *cap, StgTSO *t )
// run queue before us and steal the large block, but in that
// case the thread will just end up requesting another large
// block.
- pushOnRunQueue(cap,t);
return rtsFalse; /* not actually GC'ing */
}
}
+ // if we got here because we exceeded large_alloc_lim, then
+ // proceed straight to GC.
+ if (g0->n_new_large_words >= large_alloc_lim) {
+ return rtsTrue;
+ }
+
+ // Otherwise, we just ran out of space in the current nursery.
+ // Grab another nursery if we can.
if (getNewNursery(cap)) {
debugTrace(DEBUG_sched, "thread %ld got a new nursery", t->id);
- pushOnRunQueue(cap,t);
return rtsFalse;
}
- if (cap->r.rHpLim == NULL || cap->context_switch) {
- // Sometimes we miss a context switch, e.g. when calling
- // primitives in a tight loop, MAYBE_GC() doesn't check the
- // context switch flag, and we end up waiting for a GC.
- // See #1984, and concurrent/should_run/1984
- cap->context_switch = 0;
- appendToRunQueue(cap,t);
- } else {
- pushOnRunQueue(cap,t);
- }
return rtsTrue;
/* actual GC is done at the end of the while loop in schedule() */
}