X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2Fsm%2FGCUtils.c;h=cee17c439a0ddf48084370155da620088ce4b8b5;hp=61b72b6c0af8baea35bbbebb8cb1909257908342;hb=d5bd3e829c47c03157cf41cad581d2df44dfd81b;hpb=9e5fe6be620eaf03a86f1321bef603ca43699a3c diff --git a/rts/sm/GCUtils.c b/rts/sm/GCUtils.c index 61b72b6..cee17c4 100644 --- a/rts/sm/GCUtils.c +++ b/rts/sm/GCUtils.c @@ -12,73 +12,172 @@ * ---------------------------------------------------------------------------*/ #include "Rts.h" +#include "RtsFlags.h" #include "Storage.h" #include "GC.h" #include "GCUtils.h" +#include "Printer.h" + +#ifdef THREADED_RTS +SpinLock gc_alloc_block_sync; +#endif + +bdescr * +allocBlock_sync(void) +{ + bdescr *bd; + ACQUIRE_SPIN_LOCK(&gc_alloc_block_sync); + bd = allocBlock(); + RELEASE_SPIN_LOCK(&gc_alloc_block_sync); + return bd; +} /* ----------------------------------------------------------------------------- - Allocate a new to-space block in the given step. + Workspace utilities -------------------------------------------------------------------------- */ bdescr * -gc_alloc_block(step *stp) +grab_todo_block (step_workspace *ws) { - bdescr *bd = allocBlock(); - bd->gen_no = stp->gen_no; - bd->step = stp; + bdescr *bd; + step *stp; + + stp = ws->stp; + bd = NULL; + + if (ws->buffer_todo_bd) + { + bd = ws->buffer_todo_bd; + ASSERT(bd->link == NULL); + ws->buffer_todo_bd = NULL; + return bd; + } + + ACQUIRE_SPIN_LOCK(&stp->sync_todo); + if (stp->todos) { + bd = stp->todos; + stp->todos = bd->link; + bd->link = NULL; + } + RELEASE_SPIN_LOCK(&stp->sync_todo); + return bd; +} + +static void +push_todo_block (bdescr *bd, step *stp) +{ + ASSERT(bd->link == NULL); + ACQUIRE_SPIN_LOCK(&stp->sync_todo); + bd->link = stp->todos; + stp->todos = bd; + RELEASE_SPIN_LOCK(&stp->sync_todo); +} + +void +push_scan_block (bdescr *bd, step_workspace *ws) +{ + ASSERT(bd != NULL); + ASSERT(bd->link == NULL); + + // update stats: this is a block that has been copied & scavenged + copied += bd->free - bd->start; + + // put the scan block *second* in ws->scavd_list. The first block + // in this list is for evacuating objects that don't need to be + // scavenged. + bd->link = ws->scavd_list->link; + ws->scavd_list->link = bd; + ws->n_scavd_blocks ++; + + IF_DEBUG(sanity, + ASSERT(countBlocks(ws->scavd_list) == ws->n_scavd_blocks)); +} + +bdescr * +gc_alloc_todo_block (step_workspace *ws) +{ + bdescr *bd; + + // If we already have a todo block, it must be full, so we push it + // out: first to the buffer_todo_bd, then to the step. BUT, don't + // push out the block out if it is already the scan block. + if (ws->todo_bd != NULL && ws->scan_bd != ws->todo_bd) { + ASSERT(ws->todo_bd->link == NULL); + if (ws->buffer_todo_bd != NULL) { + ASSERT(ws->buffer_todo_bd->link == NULL); + push_todo_block(ws->buffer_todo_bd, ws->stp); + } + ws->buffer_todo_bd = ws->todo_bd; + ws->todo_bd = NULL; + } + + bd = allocBlock_sync(); + + bd->gen_no = ws->stp->gen_no; + bd->step = ws->stp; bd->link = NULL; // blocks in to-space in generations up to and including N // get the BF_EVACUATED flag. - if (stp->gen_no <= N) { + if (ws->stp->gen_no <= N) { bd->flags = BF_EVACUATED; } else { bd->flags = 0; } - - // Start a new to-space block, chain it on after the previous one. - if (stp->hp_bd != NULL) { - stp->hp_bd->free = stp->hp; - stp->hp_bd->link = bd; - } - - stp->hp_bd = bd; - stp->hp = bd->start; - stp->hpLim = stp->hp + BLOCK_SIZE_W; - - stp->n_blocks++; - new_blocks++; + + ws->todo_bd = bd; return bd; } bdescr * -gc_alloc_scavd_block(step *stp) +gc_alloc_scavd_block (step_workspace *ws) { - bdescr *bd = allocBlock(); - bd->gen_no = stp->gen_no; - bd->step = stp; + bdescr *bd; + + bd = allocBlock_sync(); + + bd->gen_no = ws->stp->gen_no; + bd->step = ws->stp; // blocks in to-space in generations up to and including N // get the BF_EVACUATED flag. - if (stp->gen_no <= N) { + if (ws->stp->gen_no <= N) { bd->flags = BF_EVACUATED; } else { bd->flags = 0; } - bd->link = stp->blocks; - stp->blocks = bd; - - if (stp->scavd_hp != NULL) { - Bdescr(stp->scavd_hp)->free = stp->scavd_hp; + // update stats: this is a block that has been copied only + if (ws->scavd_list != NULL) { + scavd_copied += ws->scavd_list->free - ws->scavd_list->start; } - stp->scavd_hp = bd->start; - stp->scavd_hpLim = stp->scavd_hp + BLOCK_SIZE_W; - stp->n_blocks++; - new_scavd_blocks++; + bd->link = ws->scavd_list; + ws->scavd_list = bd; + ws->n_scavd_blocks++; return bd; } +/* ----------------------------------------------------------------------------- + * Debugging + * -------------------------------------------------------------------------- */ + +#if DEBUG +void +printMutableList(generation *gen) +{ + bdescr *bd; + StgPtr p; + + debugBelch("mutable list %p: ", gen->mut_list); + + for (bd = gen->mut_list; bd != NULL; bd = bd->link) { + for (p = bd->start; p < bd->free; p++) { + debugBelch("%p (%s), ", (void *)*p, info_type((StgClosure *)*p)); + } + } + debugBelch("\n"); +} +#endif /* DEBUG */