add another SMP assertion
[ghc-hetmet.git] / ghc / rts / Schedule.c
index 935a916..b0a8dc6 100644 (file)
@@ -445,6 +445,9 @@ schedule (Capability *initialCapability, Task *task)
     scheduleCheckBlockedThreads(cap);
 
     scheduleDetectDeadlock(cap,task);
+#if defined(THREADED_RTS)
+    cap = task->cap;    // reload cap, it might have changed
+#endif
 
     // Normally, the only way we can get here with no threads to
     // run is if a keyboard interrupt received during 
@@ -560,6 +563,8 @@ run_thread:
     // ----------------------------------------------------------------------
     // Run the current thread 
 
+    ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);
+
     prev_what_next = t->what_next;
 
     errno = t->saved_errno;
@@ -613,7 +618,7 @@ run_thread:
     // be running again, see code below.
     t->saved_errno = errno;
 
-#ifdef SMP
+#if defined(THREADED_RTS)
     // If ret is ThreadBlocked, and this Task is bound to the TSO that
     // blocked, we are in limbo - the TSO is now owned by whatever it
     // is blocked on, and may in fact already have been woken up,
@@ -678,7 +683,12 @@ run_thread:
     }
 
     if (scheduleDoHeapProfile(ready_to_gc)) { ready_to_gc = rtsFalse; }
-    if (ready_to_gc) { scheduleDoGC(cap,task,rtsFalse,GetRoots); }
+    if (ready_to_gc) {
+      scheduleDoGC(cap,task,rtsFalse,GetRoots);
+#if defined(THREADED_RTS)
+      cap = task->cap;    // reload cap, it might have changed  
+#endif
+    }
   } /* end of while() */
 
   IF_PAR_DEBUG(verbose,
@@ -915,6 +925,10 @@ scheduleDetectDeadlock (Capability *cap, Task *task)
        // exception.  Any threads thus released will be immediately
        // runnable.
        scheduleDoGC( cap, task, rtsTrue/*force  major GC*/, GetRoots );
+#if defined(THREADED_RTS)
+       cap = task->cap;    // reload cap, it might have changed
+#endif
+
        recent_activity = ACTIVITY_DONE_GC;
        
        if ( !emptyRunQueue(cap) ) return;
@@ -1857,8 +1871,19 @@ scheduleDoHeapProfile( rtsBool ready_to_gc STG_UNUSED )
     if (performHeapProfile ||
        (RtsFlags.ProfFlags.profileInterval==0 &&
         RtsFlags.ProfFlags.doHeapProfile && ready_to_gc)) {
+
+       // checking black holes is necessary before GC, otherwise
+       // there may be threads that are unreachable except by the
+       // blackhole queue, which the GC will consider to be
+       // deadlocked.
+       scheduleCheckBlackHoles(&MainCapability);
+
+       IF_DEBUG(scheduler, sched_belch("garbage collecting before heap census"));
        GarbageCollect(GetRoots, rtsTrue);
+
+       IF_DEBUG(scheduler, sched_belch("performing heap census"));
        heapCensus();
+
        performHeapProfile = rtsFalse;
        return rtsTrue;  // true <=> we already GC'd
     }
@@ -1899,7 +1924,7 @@ scheduleDoGC (Capability *cap, Task *task USED_IF_THREADS,
            IF_DEBUG(scheduler, sched_belch("someone else is trying to GC..."));
            if (cap) yieldCapability(&cap,task);
        } while (waiting_for_gc);
-       return;
+       return;  // NOTE: task->cap might have changed here
     }
 
     for (i=0; i < n_capabilities; i++) {
@@ -2266,6 +2291,8 @@ resumeThread (void *task_)
     /* We might have GC'd, mark the TSO dirty again */
     dirtyTSO(tso);
 
+    IF_DEBUG(sanity, checkTSO(tso));
+
     return &cap->r;
 }