have each GC thread call GetRoots()
authorsimonmar@microsoft.com <unknown>
Thu, 13 Dec 2007 16:50:13 +0000 (16:50 +0000)
committersimonmar@microsoft.com <unknown>
Thu, 13 Dec 2007 16:50:13 +0000 (16:50 +0000)
rts/Sparks.c
rts/Sparks.h
rts/sm/GC.c

index 0ff4ee4..2ebe5f6 100644 (file)
@@ -108,68 +108,65 @@ findSpark (Capability *cap)
  * -------------------------------------------------------------------------- */
 
 void
-markSparkQueue (evac_fn evac)
+markSparkQueue (evac_fn evac, Capability *cap)
 { 
     StgClosure **sparkp, **to_sparkp;
-    nat i, n, pruned_sparks; // stats only
+    nat n, pruned_sparks; // stats only
     StgSparkPool *pool;
-    Capability *cap;
     
     PAR_TICKY_MARK_SPARK_QUEUE_START();
     
     n = 0;
     pruned_sparks = 0;
-    for (i = 0; i < n_capabilities; i++) {
-       cap = &capabilities[i];
-       pool = &(cap->r.rSparks);
-       
-       ASSERT_SPARK_POOL_INVARIANTS(pool);
-
+    
+    pool = &(cap->r.rSparks);
+    
+    ASSERT_SPARK_POOL_INVARIANTS(pool);
+    
 #if defined(PARALLEL_HASKELL)
-       // stats only
-       n = 0;
-       pruned_sparks = 0;
+    // stats only
+    n = 0;
+    pruned_sparks = 0;
 #endif
        
-       sparkp = pool->hd;
-       to_sparkp = pool->hd;
-       while (sparkp != pool->tl) {
-           ASSERT(*sparkp!=NULL);
-           ASSERT(LOOKS_LIKE_CLOSURE_PTR(((StgClosure *)*sparkp)));
-           // ToDo?: statistics gathering here (also for GUM!)
-           if (closure_SHOULD_SPARK(*sparkp)) {
-               evac(sparkp);
-               *to_sparkp++ = *sparkp;
-               if (to_sparkp == pool->lim) {
-                   to_sparkp = pool->base;
-               }
-               n++;
-           } else {
-               pruned_sparks++;
-           }
-           sparkp++;
-           if (sparkp == pool->lim) {
-               sparkp = pool->base;
-           }
-       }
-       pool->tl = to_sparkp;
+    sparkp = pool->hd;
+    to_sparkp = pool->hd;
+    while (sparkp != pool->tl) {
+        ASSERT(*sparkp!=NULL);
+        ASSERT(LOOKS_LIKE_CLOSURE_PTR(((StgClosure *)*sparkp)));
+        // ToDo?: statistics gathering here (also for GUM!)
+        if (closure_SHOULD_SPARK(*sparkp)) {
+            evac(sparkp);
+            *to_sparkp++ = *sparkp;
+            if (to_sparkp == pool->lim) {
+                to_sparkp = pool->base;
+            }
+            n++;
+        } else {
+            pruned_sparks++;
+        }
+        sparkp++;
+        if (sparkp == pool->lim) {
+            sparkp = pool->base;
+        }
+    }
+    pool->tl = to_sparkp;
        
-       PAR_TICKY_MARK_SPARK_QUEUE_END(n);
+    PAR_TICKY_MARK_SPARK_QUEUE_END(n);
        
 #if defined(PARALLEL_HASKELL)
-       debugTrace(DEBUG_sched, 
-                  "marked %d sparks and pruned %d sparks on [%x]",
-                  n, pruned_sparks, mytid);
+    debugTrace(DEBUG_sched, 
+               "marked %d sparks and pruned %d sparks on [%x]",
+               n, pruned_sparks, mytid);
 #else
-       debugTrace(DEBUG_sched, 
-                  "marked %d sparks and pruned %d sparks",
-                  n, pruned_sparks);
+    debugTrace(DEBUG_sched, 
+               "marked %d sparks and pruned %d sparks",
+               n, pruned_sparks);
 #endif
-       
-       debugTrace(DEBUG_sched,
-                  "new spark queue len=%d; (hd=%p; tl=%p)\n",
-                  sparkPoolSize(pool), pool->hd, pool->tl);
-    }
+    
+    debugTrace(DEBUG_sched,
+               "new spark queue len=%d; (hd=%p; tl=%p)\n",
+               sparkPoolSize(pool), pool->hd, pool->tl);
 }
 
 /* -----------------------------------------------------------------------------
index f2d3c6e..1a7fbe0 100644 (file)
@@ -13,7 +13,7 @@
 StgClosure * findSpark         (Capability *cap);
 void         initSparkPools    (void);
 void         freeSparkPool     (StgSparkPool *pool);
-void         markSparkQueue    (evac_fn evac);
+void         markSparkQueue    (evac_fn evac, Capability *cap);
 void         createSparkThread (Capability *cap, StgClosure *p);
 
 INLINE_HEADER void     discardSparks  (StgSparkPool *pool);
index 847f856..af35150 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();
@@ -702,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);
@@ -717,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)
@@ -724,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
 }
 
 /* -----------------------------------------------------------------------------
@@ -973,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