summaryrefslogtreecommitdiff
path: root/rts/Capability.c
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2012-06-07 14:39:04 +0100
committerIan Lynagh <igloo@earth.li>2012-06-07 14:40:30 +0100
commit93e7e26245fbd173f6cea547cb008c7258d74442 (patch)
treeefd3eeddd53811fabd17638201c623fb906cb342 /rts/Capability.c
parent22b51daaf41820e5451cb8dadf63e2a534c3efb4 (diff)
downloadhaskell-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.c13
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]