Allow work units smaller than a block to improve load balancing
[ghc-hetmet.git] / rts / sm / Scav.c-inc
index 50c4088..6f85203 100644 (file)
@@ -1,4 +1,4 @@
-/* -----------------------------------------------------------------------------
+/* -----------------------------------------------------------------------*-c-*-
  *
  * (c) The GHC Team 1998-2006
  *
  *
  * ---------------------------------------------------------------------------*/
 
-// This file is #included into Scav.c, twice: firstly with MINOR_GC
+// This file is #included into Scav.c, twice: firstly with PARALLEL_GC
 // defined, the second time without.
 
-#ifdef MINOR_GC
-#define scavenge_block(a,b) scavenge_block0(a,b)
-#define evacuate(a) evacuate0(a)
+#ifndef PARALLEL_GC
+#define scavenge_block(a) scavenge_block1(a)
+#define evacuate(a) evacuate1(a)
+#define recordMutableGen_GC(a,b) recordMutableGen(a,b)
 #else
 #undef scavenge_block
 #undef evacuate
+#undef recordMutableGen_GC
 #endif
 
-static void scavenge_block (bdescr *bd, StgPtr scan);
+static void scavenge_block (bdescr *bd);
 
 /* -----------------------------------------------------------------------------
    Scavenge a block from the given scan pointer up to bd->free.
@@ -37,25 +39,30 @@ static void scavenge_block (bdescr *bd, StgPtr scan);
    -------------------------------------------------------------------------- */
 
 static void
-scavenge_block (bdescr *bd, StgPtr scan)
+scavenge_block (bdescr *bd)
 {
   StgPtr p, q;
   StgInfoTable *info;
   step *saved_evac_step;
+  rtsBool saved_eager_promotion;
+  step_workspace *ws;
 
-  p = scan;
+  p = bd->u.scan;
   
   debugTrace(DEBUG_gc, "scavenging block %p (gen %d, step %d) @ %p",
-            bd->start, bd->gen_no, bd->step->no, scan);
+            bd->start, bd->gen_no, bd->step->no, p);
 
   gct->evac_step = bd->step;
   saved_evac_step = gct->evac_step;
+  saved_eager_promotion = gct->eager_promotion;
   gct->failed_to_evac = rtsFalse;
 
+  ws = &gct->steps[bd->step->abs_no];
+
   // we might be evacuating into the very object that we're
   // scavenging, so we have to check the real bd->free pointer each
   // time around the loop.
-  while (p < bd->free) {
+  while (p < bd->free || (bd == ws->todo_bd && p < ws->todo_free)) {
 
     ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
     info = get_itbl((StgClosure *)p);
@@ -68,8 +75,6 @@ scavenge_block (bdescr *bd, StgPtr scan)
     case MVAR_CLEAN:
     case MVAR_DIRTY:
     { 
-       rtsBool saved_eager_promotion = gct->eager_promotion;
-
        StgMVar *mvar = ((StgMVar *)p);
        gct->eager_promotion = rtsFalse;
        evacuate((StgClosure **)&mvar->head);
@@ -87,18 +92,14 @@ scavenge_block (bdescr *bd, StgPtr scan)
     }
 
     case FUN_2_0:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
        evacuate(&((StgClosure *)p)->payload[1]);
        evacuate(&((StgClosure *)p)->payload[0]);
        p += sizeofW(StgHeader) + 2;
        break;
 
     case THUNK_2_0:
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        evacuate(&((StgThunk *)p)->payload[1]);
        evacuate(&((StgThunk *)p)->payload[0]);
        p += sizeofW(StgThunk) + 2;
@@ -111,82 +112,62 @@ scavenge_block (bdescr *bd, StgPtr scan)
        break;
        
     case THUNK_1_0:
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        evacuate(&((StgThunk *)p)->payload[0]);
        p += sizeofW(StgThunk) + 1;
        break;
        
     case FUN_1_0:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
     case CONSTR_1_0:
        evacuate(&((StgClosure *)p)->payload[0]);
        p += sizeofW(StgHeader) + 1;
        break;
        
     case THUNK_0_1:
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        p += sizeofW(StgThunk) + 1;
        break;
        
     case FUN_0_1:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
     case CONSTR_0_1:
        p += sizeofW(StgHeader) + 1;
        break;
        
     case THUNK_0_2:
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        p += sizeofW(StgThunk) + 2;
        break;
        
     case FUN_0_2:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
     case CONSTR_0_2:
        p += sizeofW(StgHeader) + 2;
        break;
        
     case THUNK_1_1:
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        evacuate(&((StgThunk *)p)->payload[0]);
        p += sizeofW(StgThunk) + 2;
        break;
 
     case FUN_1_1:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
     case CONSTR_1_1:
        evacuate(&((StgClosure *)p)->payload[0]);
        p += sizeofW(StgHeader) + 2;
        break;
        
     case FUN:
-#ifndef MINOR_GC
        scavenge_fun_srt(info);
-#endif
        goto gen_obj;
 
     case THUNK:
     {
        StgPtr end;
 
-#ifndef MINOR_GC
        scavenge_thunk_srt(info);
-#endif
        end = (P_)((StgThunk *)p)->payload + info->layout.payload.ptrs;
        for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
            evacuate((StgClosure **)p);
@@ -242,9 +223,7 @@ scavenge_block (bdescr *bd, StgPtr scan)
        break;
 
     case MUT_VAR_CLEAN:
-    case MUT_VAR_DIRTY: {
-       rtsBool saved_eager_promotion = gct->eager_promotion;
-
+    case MUT_VAR_DIRTY:
        gct->eager_promotion = rtsFalse;
        evacuate(&((StgMutVar *)p)->var);
        gct->eager_promotion = saved_eager_promotion;
@@ -256,7 +235,6 @@ scavenge_block (bdescr *bd, StgPtr scan)
        }
        p += sizeofW(StgMutVar);
        break;
-    }
 
     case CAF_BLACKHOLE:
     case SE_CAF_BLACKHOLE:
@@ -302,19 +280,17 @@ scavenge_block (bdescr *bd, StgPtr scan)
        // follow everything 
     {
        StgPtr next;
-       rtsBool saved_eager;
 
        // We don't eagerly promote objects pointed to by a mutable
        // array, but if we find the array only points to objects in
        // the same or an older generation, we mark it "clean" and
        // avoid traversing it during minor GCs.
-       saved_eager = gct->eager_promotion;
        gct->eager_promotion = rtsFalse;
        next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
        for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
            evacuate((StgClosure **)p);
        }
-       gct->eager_promotion = saved_eager;
+       gct->eager_promotion = saved_eager_promotion;
 
        if (gct->failed_to_evac) {
            ((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_DIRTY_info;
@@ -350,11 +326,10 @@ scavenge_block (bdescr *bd, StgPtr scan)
     case TSO:
     { 
        StgTSO *tso = (StgTSO *)p;
-       rtsBool saved_eager = gct->eager_promotion;
 
        gct->eager_promotion = rtsFalse;
        scavengeTSO(tso);
-       gct->eager_promotion = saved_eager;
+       gct->eager_promotion = saved_eager_promotion;
 
        if (gct->failed_to_evac) {
            tso->flags |= TSO_DIRTY;
@@ -468,5 +443,19 @@ scavenge_block (bdescr *bd, StgPtr scan)
     }
   }
 
-  debugTrace(DEBUG_gc, "   scavenged %ld bytes", (bd->free - scan) * sizeof(W_));
+  if (p > bd->free)  {
+      bd->free = p;
+  }
+
+  debugTrace(DEBUG_gc, "   scavenged %ld bytes",
+             (unsigned long)((bd->free - bd->u.scan) * sizeof(W_)));
+
+  // update stats: this is a block that has been copied & scavenged
+  gct->copied += bd->free - bd->u.scan;
+
+  bd->u.scan = bd->free;
 }
+
+#undef scavenge_block
+#undef evacuate
+#undef recordMutableGen_GC