diff options
author | Simon Marlow <marlowsd@gmail.com> | 2015-07-15 13:07:35 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2015-07-15 14:59:28 +0100 |
commit | 75fd5dc204fb6bb9014f6bba4d680facbc952faf (patch) | |
tree | e66ef6e29165eca3ac259a2645f2405a6780e5fe /rts/Schedule.c | |
parent | a592e9ffcfb288cd154bad60dc8003b781355533 (diff) | |
download | haskell-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/Schedule.c')
-rw-r--r-- | rts/Schedule.c | 31 |
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() */ } |