X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FStorage.c;h=69e441de5f6fb7e9378c04eebe79d46e47d805d4;hb=74ee9df9f9e79e7110e9d8541b84010f35c464c5;hp=7f4c723934f93d506fedd95bf7ea5fd8c153de6b;hpb=2aa877f8588da099351ef51efca3605fd87ea768;p=ghc-hetmet.git diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index 7f4c723..69e441d 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -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 @@ -87,6 +86,8 @@ 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->live_estimate = 0; stp->old_blocks = NULL; stp->n_old_blocks = 0; stp->gen = &generations[g]; @@ -95,12 +96,15 @@ initStep (step *stp, int g, int s) stp->n_large_blocks = 0; stp->scavenged_large_objects = NULL; stp->n_scavenged_large_blocks = 0; - stp->is_compacted = 0; + stp->mark = 0; + stp->compact = 0; stp->bitmap = NULL; #ifdef THREADED_RTS initSpinLock(&stp->sync_todo); initSpinLock(&stp->sync_large_objects); #endif + stp->threads = END_TSO_QUEUE; + stp->old_threads = END_TSO_QUEUE; } void @@ -165,6 +169,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; } @@ -227,11 +232,13 @@ initStorage( void ) } /* The oldest generation has one step. */ - if (RtsFlags.GcFlags.compact) { + if (RtsFlags.GcFlags.compact || RtsFlags.GcFlags.sweep) { if (RtsFlags.GcFlags.generations == 1) { - errorBelch("WARNING: compaction is incompatible with -G1; disabled"); + errorBelch("WARNING: compact/sweep is incompatible with -G1; disabled"); } else { - oldest_gen->steps[0].is_compacted = 1; + oldest_gen->steps[0].mark = 1; + if (RtsFlags.GcFlags.compact) + oldest_gen->steps[0].compact = 1; } } @@ -259,7 +266,6 @@ initStorage( void ) #ifdef THREADED_RTS initSpinLock(&gc_alloc_block_sync); - initSpinLock(&static_objects_sync); initSpinLock(&recordMutableGen_sync); whitehole_spin = 0; #endif @@ -551,6 +557,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 @@ -822,6 +844,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 @@ -985,6 +1036,7 @@ countOccupied(bdescr *bd) words = 0; for (; bd != NULL; bd = bd->link) { + ASSERT(bd->free <= bd->start + bd->blocks * BLOCK_SIZE_W); words += bd->free - bd->start; } return words; @@ -1000,7 +1052,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; @@ -1008,8 +1060,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; @@ -1033,14 +1084,27 @@ calcNeeded(void) for (s = 0; s < generations[g].n_steps; s++) { if (g == 0 && s == 0) { continue; } stp = &generations[g].steps[s]; + + // we need at least this much space + needed += stp->n_blocks + stp->n_large_blocks; + + // any additional space needed to collect this gen next time? if (g == 0 || // always collect gen 0 (generations[g].steps[0].n_blocks + generations[g].steps[0].n_large_blocks - > generations[g].max_blocks - && stp->is_compacted == 0)) { - needed += 2 * stp->n_blocks + stp->n_large_blocks; - } else { - needed += stp->n_blocks + stp->n_large_blocks; + > generations[g].max_blocks)) { + // we will collect this gen next time + if (stp->mark) { + // bitmap: + needed += stp->n_blocks / BITS_IN(W_); + // mark stack: + needed += stp->n_blocks / 100; + } + if (stp->compact) { + continue; // no additional space needed for compaction + } else { + needed += stp->n_blocks; + } } } } @@ -1262,6 +1326,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) {