X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FGC.c;h=079ef83b4d6a86e84fb2994e089d503fd4d74c5b;hb=78956377551e1433b0a87128c5f88c254ec46b40;hp=978b7a0a20b76bd642a5f6651dbbcd979e35f4d5;hpb=49780c2e25cfbe821d585c5a31cb95aa49f41f14;p=ghc-hetmet.git diff --git a/rts/sm/GC.c b/rts/sm/GC.c index 978b7a0..079ef83 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -39,7 +39,6 @@ #include "Trace.h" #include "RetainerProfile.h" #include "RaiseAsync.h" -#include "Sparks.h" #include "Papi.h" #include "GC.h" @@ -183,7 +182,6 @@ GarbageCollect ( rtsBool force_major_gc ) bdescr *bd; step *stp; lnat live, allocated, max_copied, avg_copied, slop; - lnat oldgen_saved_blocks = 0; gc_thread *saved_gct; nat g, s, t, n; @@ -377,6 +375,9 @@ GarbageCollect ( rtsBool force_major_gc ) // Update pointers from the Task list update_task_list(); + // Update pointers from capabilities (probably just the spark queues) + updateCapabilitiesPostGC(); + // Now see which stable names are still alive. gcStablePtrTable(); @@ -389,14 +390,6 @@ GarbageCollect ( rtsBool force_major_gc ) #endif // NO MORE EVACUATION AFTER THIS POINT! - // Finally: compaction of the oldest generation. - if (major_gc && oldest_gen->steps[0].is_compacted) { - // save number of blocks for stats - oldgen_saved_blocks = oldest_gen->steps[0].n_old_blocks; - compact(gct->scavenged_static_objects); - } - - IF_DEBUG(sanity, checkGlobalTSOList(rtsFalse)); // Two-space collector: free the old to-space. // g0s0->old_blocks is the old nursery @@ -408,9 +401,7 @@ GarbageCollect ( rtsBool force_major_gc ) } } - // For each workspace, in each thread: - // * clear the BF_EVACUATED flag from each copied block - // * move the copied blocks to the step + // For each workspace, in each thread, move the copied blocks to the step { gc_thread *thr; step_workspace *ws; @@ -438,7 +429,6 @@ GarbageCollect ( rtsBool force_major_gc ) prev = NULL; for (bd = ws->scavd_list; bd != NULL; bd = bd->link) { - bd->flags &= ~BF_EVACUATED; // now from-space ws->step->n_words += bd->free - bd->start; prev = bd; } @@ -447,6 +437,23 @@ GarbageCollect ( rtsBool force_major_gc ) ws->step->blocks = ws->scavd_list; } ws->step->n_blocks += ws->n_scavd_blocks; + } + } + + // Add all the partial blocks *after* we've added all the full + // blocks. This is so that we can grab the partial blocks back + // again and try to fill them up in the next GC. + for (t = 0; t < n_gc_threads; t++) { + thr = gc_threads[t]; + + // not step 0 + if (RtsFlags.GcFlags.generations == 1) { + s = 0; + } else { + s = 1; + } + for (; s < total_steps; s++) { + ws = &thr->steps[s]; prev = NULL; for (bd = ws->part_list; bd != NULL; bd = next) { @@ -460,7 +467,6 @@ GarbageCollect ( rtsBool force_major_gc ) freeGroup(bd); ws->n_part_blocks--; } else { - bd->flags &= ~BF_EVACUATED; // now from-space ws->step->n_words += bd->free - bd->start; prev = bd; } @@ -477,6 +483,13 @@ GarbageCollect ( rtsBool force_major_gc ) } } + // Finally: compaction of the oldest generation. + if (major_gc && oldest_gen->steps[0].is_compacted) { + compact(gct->scavenged_static_objects); + } + + IF_DEBUG(sanity, checkGlobalTSOList(rtsFalse)); + /* run through all the generations/steps and tidy up */ copied = 0; @@ -540,20 +553,21 @@ GarbageCollect ( rtsBool force_major_gc ) if (!(g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1)) { if (stp->is_compacted) { - // for a compacted step, just shift the new to-space - // onto the front of the now-compacted existing blocks. - for (bd = stp->blocks; bd != NULL; bd = bd->link) { - bd->flags &= ~BF_EVACUATED; // now from-space - stp->n_words += bd->free - bd->start; - } // tack the new blocks on the end of the existing blocks if (stp->old_blocks != NULL) { for (bd = stp->old_blocks; bd != NULL; bd = next) { + stp->n_words += bd->free - bd->start; + // NB. this step might not be compacted next // time, so reset the BF_COMPACTED flags. // They are set before GC if we're going to // compact. (search for BF_COMPACTED above). bd->flags &= ~BF_COMPACTED; + + // between GCs, all blocks in the heap except + // for the nursery have the BF_EVACUATED flag set. + bd->flags |= BF_EVACUATED; + next = bd->link; if (next == NULL) { bd->link = stp->blocks; @@ -585,10 +599,6 @@ GarbageCollect ( rtsBool force_major_gc ) bd = next; } - // update the count of blocks used by large objects - for (bd = stp->scavenged_large_objects; bd != NULL; bd = bd->link) { - bd->flags &= ~BF_EVACUATED; - } stp->large_objects = stp->scavenged_large_objects; stp->n_large_blocks = stp->n_scavenged_large_blocks; @@ -601,7 +611,6 @@ GarbageCollect ( rtsBool force_major_gc ) */ for (bd = stp->scavenged_large_objects; bd; bd = next) { next = bd->link; - bd->flags &= ~BF_EVACUATED; dbl_link_onto(bd, &stp->large_objects); } @@ -685,6 +694,7 @@ GarbageCollect ( rtsBool force_major_gc ) // send exceptions to any threads which were about to die RELEASE_SM_LOCK; resurrectThreads(resurrected_threads); + performPendingThrowTos(exception_threads); ACQUIRE_SM_LOCK; // Update the stable pointer hash table. @@ -899,7 +909,7 @@ loop: gct->thread_index, r); while (gc_running_threads != 0) { - usleep(1); + // usleep(1); if (any_work()) { inc_running(); goto loop; @@ -1071,14 +1081,19 @@ init_collected_gen (nat g, nat n_threads) for (s = 0; s < generations[g].n_steps; s++) { + stp = &generations[g].steps[s]; + ASSERT(stp->gen_no == g); + + // we'll construct a new list of threads in this step + // during GC, throw away the current list. + stp->old_threads = stp->threads; + stp->threads = END_TSO_QUEUE; + // generation 0, step 0 doesn't need to-space if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) { continue; } - stp = &generations[g].steps[s]; - ASSERT(stp->gen_no == g); - // deprecate the existing blocks stp->old_blocks = stp->blocks; stp->n_old_blocks = stp->n_blocks; @@ -1095,7 +1110,12 @@ init_collected_gen (nat g, nat n_threads) stp->scavenged_large_objects = NULL; stp->n_scavenged_large_blocks = 0; - // mark the large objects as not evacuated yet + // mark the small objects as from-space + for (bd = stp->old_blocks; bd; bd = bd->link) { + bd->flags &= ~BF_EVACUATED; + } + + // mark the large objects as from-space for (bd = stp->large_objects; bd; bd = bd->link) { bd->flags &= ~BF_EVACUATED; } @@ -1184,11 +1204,12 @@ init_uncollected_gen (nat g, nat threads) stp->n_scavenged_large_blocks = 0; } - for (t = 0; t < threads; t++) { - for (s = 0; s < generations[g].n_steps; s++) { + for (s = 0; s < generations[g].n_steps; s++) { + stp = &generations[g].steps[s]; + + for (t = 0; t < threads; t++) { ws = &gc_threads[t]->steps[g * RtsFlags.GcFlags.steps + s]; - stp = ws->step; ws->buffer_todo_bd = NULL; ws->todo_large_objects = NULL; @@ -1219,8 +1240,26 @@ init_uncollected_gen (nat g, nat threads) alloc_todo_block(ws,0); } } + + // deal out any more partial blocks to the threads' part_lists + t = 0; + while (stp->blocks && isPartiallyFull(stp->blocks)) + { + bd = stp->blocks; + stp->blocks = bd->link; + ws = &gc_threads[t]->steps[g * RtsFlags.GcFlags.steps + s]; + bd->link = ws->part_list; + ws->part_list = bd; + ws->n_part_blocks += 1; + bd->u.scan = bd->free; + stp->n_blocks -= 1; + stp->n_words -= bd->free - bd->start; + t++; + if (t == n_gc_threads) t = 0; + } } + // Move the private mutable lists from each capability onto the // main mutable list for the generation. for (i = 0; i < n_capabilities; i++) {