allocateInGen(): increase alloc_blocks (#2747)
[ghc-hetmet.git] / rts / Schedule.c
index 2e9d0dd..ca6e426 100644 (file)
@@ -399,6 +399,7 @@ schedule (Capability *initialCapability, Task *task)
     //     ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);
     }
 
+  yield:
     scheduleYield(&cap,task);
     if (emptyRunQueue(cap)) continue; // look for work again
 #endif
@@ -565,7 +566,7 @@ run_thread:
        debugTrace(DEBUG_sched,
                   "--<< thread %lu (%s) stopped: blocked",
                   (unsigned long)t->id, whatNext_strs[t->what_next]);
-       continue;
+        goto yield;
     }
 #endif
 
@@ -713,7 +714,8 @@ scheduleYield (Capability **pcap, Task *task)
     Capability *cap = *pcap;
 
     // if we have work, and we don't need to give up the Capability, continue.
-    if (!emptyRunQueue(cap) && !shouldYieldCapability(cap,task))
+    if (!shouldYieldCapability(cap,task) && 
+        (!emptyRunQueue(cap) || blackholes_need_checking))
         return;
 
     // otherwise yield (sleep), and keep yielding if necessary.
@@ -933,8 +935,13 @@ scheduleCheckBlackHoles (Capability *cap)
     {
        ACQUIRE_LOCK(&sched_mutex);
        if ( blackholes_need_checking ) {
-           checkBlackHoles(cap);
            blackholes_need_checking = rtsFalse;
+            // important that we reset the flag *before* checking the
+            // blackhole queue, otherwise we could get deadlock.  This
+            // happens as follows: we wake up a thread that
+            // immediately runs on another Capability, blocks on a
+            // blackhole, and then we reset the blackholes_need_checking flag.
+           checkBlackHoles(cap);
        }
        RELEASE_LOCK(&sched_mutex);
     }
@@ -2113,14 +2120,13 @@ exitScheduler(
        boundTaskExiting(task);
        stopTaskManager();
     }
-#else
-    freeCapability(&MainCapability);
 #endif
 }
 
 void
 freeScheduler( void )
 {
+    freeCapabilities();
     freeTaskManager();
     if (n_capabilities != 1) {
         stgFree(capabilities);