bugfix: check for NULL before testing isPartiallyFull(stp->blocks)
[ghc-hetmet.git] / rts / sm / GC.c
index 8aca959..244da13 100644 (file)
@@ -344,6 +344,11 @@ GarbageCollect ( rtsBool force_major_gc )
   gct->evac_step = 0;
   GetRoots(mark_root);
 
+#if defined(RTS_USER_SIGNALS)
+  // mark the signal handlers (signals should be already blocked)
+  markSignalHandlers(mark_root);
+#endif
+
   // Mark the weak pointer list, and prepare to detect dead weak pointers.
   markWeakPtrList();
   initWeakForGC();
@@ -695,11 +700,6 @@ GarbageCollect ( rtsBool force_major_gc )
      
    ------------------------------------------------------------------------ */
 
-/* This has to be protected either by the scheduler monitor, or by the
-       garbage collection monitor (probably the latter).
-       KH @ 25/10/99
-*/
-
 void
 GetRoots( evac_fn evac )
 {
@@ -707,7 +707,12 @@ GetRoots( evac_fn evac )
     Capability *cap;
     Task *task;
 
-    for (i = 0; i < n_capabilities; i++) {
+    // Each GC thread is responsible for following roots from the
+    // Capability of the same number.  There will usually be the same
+    // or fewer Capabilities as GC threads, but just in case there
+    // are more, we mark every Capability whose number is the GC
+    // thread's index plus a multiple of the number of GC threads.
+    for (i = gct->thread_index; i < n_capabilities; i += n_gc_threads) {
        cap = &capabilities[i];
        evac((StgClosure **)(void *)&cap->run_queue_hd);
        evac((StgClosure **)(void *)&cap->run_queue_tl);
@@ -722,6 +727,9 @@ GetRoots( evac_fn evac )
            evac((StgClosure **)(void *)&task->suspended_tso);
        }
 
+#if defined(THREADED_RTS)
+        markSparkQueue(evac,cap);
+#endif
     }
     
 #if !defined(THREADED_RTS)
@@ -729,17 +737,6 @@ GetRoots( evac_fn evac )
     evac((StgClosure **)(void *)&blocked_queue_tl);
     evac((StgClosure **)(void *)&sleeping_queue);
 #endif 
-
-    // evac((StgClosure **)&blackhole_queue);
-
-#if defined(THREADED_RTS)
-    markSparkQueue(evac);
-#endif
-    
-#if defined(RTS_USER_SIGNALS)
-    // mark the signal handlers (signals should be already blocked)
-    markSignalHandlers(evac);
-#endif
 }
 
 /* -----------------------------------------------------------------------------
@@ -978,6 +975,10 @@ gc_thread_work (void)
     // GarbageCollect(), or this is a worker thread and the main
     // thread bumped gc_running_threads before waking us up.
 
+    // Every thread evacuates some roots.
+    gct->evac_step = 0;
+    GetRoots(mark_root);
+
 loop:
     scavenge_loop();
     // scavenge_loop() only exits when there's no work to do
@@ -1236,7 +1237,7 @@ init_uncollected_gen (nat g, nat threads)
 
            // If the block at the head of the list in this generation
            // is less than 3/4 full, then use it as a todo block.
-           if (isPartiallyFull(stp->blocks))
+           if (stp->blocks && isPartiallyFull(stp->blocks))
            {
                ws->todo_bd = stp->blocks;
                 ws->todo_free = ws->todo_bd->free;