fix allocated blocks calculation, and add more sanity checks
[ghc-hetmet.git] / rts / sm / Storage.c
index 6b16cc4..b76fcf4 100644 (file)
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------------
  *
- * (c) The GHC Team, 1998-2006
+ * (c) The GHC Team, 1998-2008
  *
  * Storage manager front end
  *
@@ -30,7 +30,6 @@
 #include "OSMem.h"
 #include "Trace.h"
 #include "GC.h"
-#include "GCUtils.h"
 #include "Evac.h"
 
 #include <stdlib.h>
@@ -87,6 +86,7 @@ initStep (step *stp, int g, int s)
     stp->abs_no = RtsFlags.GcFlags.steps * g + s;
     stp->blocks = NULL;
     stp->n_blocks = 0;
+    stp->n_words = 0;
     stp->old_blocks = NULL;
     stp->n_old_blocks = 0;
     stp->gen = &generations[g];
@@ -101,6 +101,8 @@ initStep (step *stp, int g, int s)
     initSpinLock(&stp->sync_todo);
     initSpinLock(&stp->sync_large_objects);
 #endif
+    stp->threads = END_TSO_QUEUE;
+    stp->old_threads = END_TSO_QUEUE;
 }
 
 void
@@ -165,6 +167,7 @@ initStorage( void )
     gen->no = g;
     gen->mut_list = allocBlock();
     gen->collections = 0;
+    gen->par_collections = 0;
     gen->failed_promotions = 0;
     gen->max_blocks = 0;
   }
@@ -550,6 +553,22 @@ resizeNurseries (nat blocks)
     resizeNurseriesFixed(blocks / n_nurseries);
 }
 
+
+/* -----------------------------------------------------------------------------
+   move_TSO is called to update the TSO structure after it has been
+   moved from one place to another.
+   -------------------------------------------------------------------------- */
+
+void
+move_TSO (StgTSO *src, StgTSO *dest)
+{
+    ptrdiff_t diff;
+
+    // relocate the stack pointer... 
+    diff = (StgPtr)dest - (StgPtr)src; // In *words* 
+    dest->sp = (StgPtr)dest->sp + diff;
+}
+
 /* -----------------------------------------------------------------------------
    The allocate() interface
 
@@ -821,6 +840,35 @@ dirty_MUT_VAR(StgRegTable *reg, StgClosure *p)
     }
 }
 
+// Setting a TSO's link field with a write barrier.
+// It is *not* necessary to call this function when
+//    * setting the link field to END_TSO_QUEUE
+//    * putting a TSO on the blackhole_queue
+//    * setting the link field of the currently running TSO, as it
+//      will already be dirty.
+void
+setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target)
+{
+    bdescr *bd;
+    if ((tso->flags & (TSO_DIRTY|TSO_LINK_DIRTY)) == 0) {
+        tso->flags |= TSO_LINK_DIRTY;
+       bd = Bdescr((StgPtr)tso);
+       if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no);
+    }
+    tso->_link = target;
+}
+
+void
+dirty_TSO (Capability *cap, StgTSO *tso)
+{
+    bdescr *bd;
+    if ((tso->flags & (TSO_DIRTY|TSO_LINK_DIRTY)) == 0) {
+       bd = Bdescr((StgPtr)tso);
+       if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no);
+    }
+    tso->flags |= TSO_DIRTY;
+}
+
 /*
    This is the write barrier for MVARs.  An MVAR_CLEAN objects is not
    on the mutable list; a MVAR_DIRTY is.  When written to, a
@@ -999,7 +1047,7 @@ calcLiveWords(void)
     step *stp;
     
     if (RtsFlags.GcFlags.generations == 1) {
-        return countOccupied(g0s0->blocks) + countOccupied(g0s0->large_objects);
+        return g0s0->n_words + countOccupied(g0s0->large_objects);
     }
     
     live = 0;
@@ -1007,8 +1055,7 @@ calcLiveWords(void)
         for (s = 0; s < generations[g].n_steps; s++) {
             if (g == 0 && s == 0) continue; 
             stp = &generations[g].steps[s];
-            live += countOccupied(stp->blocks) + 
-                    countOccupied(stp->large_objects);
+            live += stp->n_words + countOccupied(stp->large_objects);
         } 
     }
     return live;
@@ -1261,6 +1308,9 @@ memInventory (rtsBool show)
 #define MB(n) (((n) * BLOCK_SIZE_W) / ((1024*1024)/sizeof(W_)))
 
   leak = live_blocks + free_blocks != mblocks_allocated * BLOCKS_PER_MBLOCK;
+
+  ASSERT(n_alloc_blocks == live_blocks);
+
   if (show || leak)
   {
       if (leak) {