X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FSanity.c;fp=rts%2Fsm%2FSanity.c;h=8ebb9a251347533ade4046a5ecf41832d8724f15;hb=18896fa2b06844407fd1e0d3f85cd3db97a96ff4;hp=65a70fa05c9bc3259ab27cd55e2adcb4e9884053;hpb=8d809e0a8354e00078529eecb00db843c1602abe;p=ghc-hetmet.git diff --git a/rts/sm/Sanity.c b/rts/sm/Sanity.c index 65a70fa..8ebb9a2 100644 --- a/rts/sm/Sanity.c +++ b/rts/sm/Sanity.c @@ -21,6 +21,7 @@ #include "RtsUtils.h" #include "sm/Storage.h" #include "sm/BlockAlloc.h" +#include "GCThread.h" #include "Sanity.h" #include "Schedule.h" #include "Apply.h" @@ -468,17 +469,10 @@ checkClosure( StgClosure* p ) all the objects in the remainder of the chain. -------------------------------------------------------------------------- */ -void -checkHeap(bdescr *bd) +void checkHeapChain (bdescr *bd) { StgPtr p; -#if defined(THREADED_RTS) - // heap sanity checking doesn't work with SMP, because we can't - // zero the slop (see Updates.h). - return; -#endif - for (; bd != NULL; bd = bd->link) { if(!(bd->flags & BF_SWEPT)) { p = bd->start; @@ -496,7 +490,7 @@ checkHeap(bdescr *bd) } } -void +void checkHeapChunk(StgPtr start, StgPtr end) { StgPtr p; @@ -587,6 +581,24 @@ checkGlobalTSOList (rtsBool checkTSOs) ASSERT(Bdescr((P_)tso)->gen_no == 0 || (tso->flags & TSO_MARKED)); tso->flags &= ~TSO_MARKED; } + + { + StgStack *stack; + StgUnderflowFrame *frame; + + stack = tso->stackobj; + while (1) { + if (stack->dirty & 1) { + ASSERT(Bdescr((P_)stack)->gen_no == 0 || (stack->dirty & TSO_MARKED)); + stack->dirty &= ~TSO_MARKED; + } + frame = (StgUnderflowFrame*) (stack->stack + stack->stack_size + - sizeofW(StgUnderflowFrame)); + if (frame->info != &stg_stack_underflow_frame_info + || frame->next_chunk == (StgStack*)END_TSO_QUEUE) break; + stack = frame->next_chunk; + } + } } } } @@ -595,7 +607,7 @@ checkGlobalTSOList (rtsBool checkTSOs) Check mutable list sanity. -------------------------------------------------------------------------- */ -void +static void checkMutableList( bdescr *mut_bd, nat gen ) { bdescr *bd; @@ -605,25 +617,37 @@ checkMutableList( bdescr *mut_bd, nat gen ) for (bd = mut_bd; bd != NULL; bd = bd->link) { for (q = bd->start; q < bd->free; q++) { p = (StgClosure *)*q; - ASSERT(!HEAP_ALLOCED(p) || Bdescr((P_)p)->gen_no == gen); - if (get_itbl(p)->type == TSO) { + ASSERT(!HEAP_ALLOCED(p) || Bdescr((P_)p)->gen_no == gen); + checkClosure(p); + + switch (get_itbl(p)->type) { + case TSO: ((StgTSO *)p)->flags |= TSO_MARKED; + break; + case STACK: + ((StgStack *)p)->dirty |= TSO_MARKED; + break; } - } + } } } -void -checkMutableLists (rtsBool checkTSOs) +static void +checkLocalMutableLists (nat cap_no) { - nat g, i; + nat g; + for (g = 1; g < RtsFlags.GcFlags.generations; g++) { + checkMutableList(capabilities[cap_no].mut_lists[g], g); + } +} - for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - for (i = 0; i < n_capabilities; i++) { - checkMutableList(capabilities[i].mut_lists[g], g); - } +static void +checkMutableLists (void) +{ + nat i; + for (i = 0; i < n_capabilities; i++) { + checkLocalMutableLists(i); } - checkGlobalTSOList(checkTSOs); } /* @@ -677,7 +701,8 @@ checkNurserySanity (nursery *nursery) prev = NULL; for (bd = nursery->blocks; bd != NULL; bd = bd->link) { - ASSERT(bd->u.back == prev); + ASSERT(bd->gen == g0); + ASSERT(bd->u.back == prev); prev = bd; blocks += bd->blocks; } @@ -685,41 +710,59 @@ checkNurserySanity (nursery *nursery) ASSERT(blocks == nursery->n_blocks); } +static void checkGeneration (generation *gen, + rtsBool after_major_gc USED_IF_THREADS) +{ + nat n; + gen_workspace *ws; + + ASSERT(countBlocks(gen->blocks) == gen->n_blocks); + ASSERT(countBlocks(gen->large_objects) == gen->n_large_blocks); + +#if defined(THREADED_RTS) + // heap sanity checking doesn't work with SMP, because we can't + // zero the slop (see Updates.h). However, we can sanity-check + // the heap after a major gc, because there is no slop. + if (!after_major_gc) return; +#endif + + checkHeapChain(gen->blocks); + + for (n = 0; n < n_capabilities; n++) { + ws = &gc_threads[n]->gens[gen->no]; + checkHeapChain(ws->todo_bd); + checkHeapChain(ws->part_list); + checkHeapChain(ws->scavd_list); + } + + checkLargeObjects(gen->large_objects); +} /* Full heap sanity check. */ -void -checkSanity( rtsBool check_heap ) +static void checkFullHeap (rtsBool after_major_gc) { nat g, n; for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - ASSERT(countBlocks(generations[g].blocks) - == generations[g].n_blocks); - ASSERT(countBlocks(generations[g].large_objects) - == generations[g].n_large_blocks); - if (check_heap) { - checkHeap(generations[g].blocks); - } - checkLargeObjects(generations[g].large_objects); + checkGeneration(&generations[g], after_major_gc); } - for (n = 0; n < n_capabilities; n++) { checkNurserySanity(&nurseries[n]); } - +} + +void checkSanity (rtsBool after_gc, rtsBool major_gc) +{ + checkFullHeap(after_gc && major_gc); + checkFreeListSanity(); -#if defined(THREADED_RTS) // always check the stacks in threaded mode, because checkHeap() // does nothing in this case. - checkMutableLists(rtsTrue); -#else - if (check_heap) { - checkMutableLists(rtsFalse); - } else { - checkMutableLists(rtsTrue); + if (after_gc) { + checkMutableLists(); + checkGlobalTSOList(rtsTrue); } -#endif } // If memInventory() calculates that we have a memory leak, this @@ -732,18 +775,21 @@ checkSanity( rtsBool check_heap ) static void findMemoryLeak (void) { - nat g, i; - for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - for (i = 0; i < n_capabilities; i++) { - markBlocks(capabilities[i].mut_lists[g]); - } - markBlocks(generations[g].blocks); - markBlocks(generations[g].large_objects); - } + nat g, i; + for (g = 0; g < RtsFlags.GcFlags.generations; g++) { + for (i = 0; i < n_capabilities; i++) { + markBlocks(capabilities[i].mut_lists[g]); + markBlocks(gc_threads[i]->gens[g].part_list); + markBlocks(gc_threads[i]->gens[g].scavd_list); + markBlocks(gc_threads[i]->gens[g].todo_bd); + } + markBlocks(generations[g].blocks); + markBlocks(generations[g].large_objects); + } - for (i = 0; i < n_capabilities; i++) { - markBlocks(nurseries[i].blocks); - } + for (i = 0; i < n_capabilities; i++) { + markBlocks(nurseries[i].blocks); + } #ifdef PROFILING // TODO: @@ -823,6 +869,9 @@ memInventory (rtsBool show) gen_blocks[g] = 0; for (i = 0; i < n_capabilities; i++) { gen_blocks[g] += countBlocks(capabilities[i].mut_lists[g]); + gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].part_list); + gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].scavd_list); + gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].todo_bd); } gen_blocks[g] += genBlocks(&generations[g]); }