diff options
author | Ian Lynagh <igloo@earth.li> | 2012-06-07 14:39:04 +0100 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2012-06-07 14:40:30 +0100 |
commit | 93e7e26245fbd173f6cea547cb008c7258d74442 (patch) | |
tree | efd3eeddd53811fabd17638201c623fb906cb342 /rts/Capability.c | |
parent | 22b51daaf41820e5451cb8dadf63e2a534c3efb4 (diff) | |
download | haskell-93e7e26245fbd173f6cea547cb008c7258d74442.tar.gz |
scheduleYield: avoid doing a GC again if we just did one
If we are interrupted to do a GC, then we do not immediately do another
one. This avoids a starvation situation where one Capability keeps
forcing a GC and the other Capabilities make no progress at all.
Diffstat (limited to 'rts/Capability.c')
-rw-r--r-- | rts/Capability.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/rts/Capability.c b/rts/Capability.c index b3b7629e54..8d211b5a61 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -679,18 +679,21 @@ waitForReturnCapability (Capability **pCap, Task *task) * yieldCapability * ------------------------------------------------------------------------- */ -void -yieldCapability (Capability** pCap, Task *task) +/* See Note [GC livelock] in Schedule.c for why we have gcAllowed + and return the rtsBool */ +rtsBool /* Did we GC? */ +yieldCapability (Capability** pCap, Task *task, rtsBool gcAllowed) { Capability *cap = *pCap; - if (pending_sync == SYNC_GC_PAR) { + if ((pending_sync == SYNC_GC_PAR) && gcAllowed) { traceEventGcStart(cap); gcWorkerThread(cap); traceEventGcEnd(cap); traceSparkCounters(cap); // See Note [migrated bound threads 2] - if (task->cap == cap) return; + if (task->cap == cap) { + return rtsTrue; } debugTrace(DEBUG_sched, "giving up capability %d", cap->no); @@ -756,7 +759,7 @@ yieldCapability (Capability** pCap, Task *task) ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task); - return; + return rtsFalse; } // Note [migrated bound threads] |