X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FGC.c;h=ee3e17089a40ffcfb3d4bfb472f7522237ac42ba;hb=888b4e89a4a4e3f39a3ba567c796b3a79b63bf61;hp=dc4c68fe75ec40daad1b3a9daea7d2e9e659d3b8;hpb=214b3663d5d7598c13643f9221e43d5a7735b47f;p=ghc-hetmet.git diff --git a/rts/sm/GC.c b/rts/sm/GC.c index dc4c68f..ee3e170 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -140,7 +140,6 @@ static nat initialise_N (rtsBool force_major_gc); static void init_collected_gen (nat g, nat threads); static void init_uncollected_gen (nat g, nat threads); static void init_gc_thread (gc_thread *t); -static void update_task_list (void); static void resize_generations (void); static void resize_nursery (void); static void start_gc_threads (void); @@ -396,13 +395,6 @@ SET_GCT(gc_threads[0]); // The other threads are now stopped. We might recurse back to // here, but from now on this is the only thread. - // if any blackholes are alive, make the threads that wait on - // them alive too. - if (traverseBlackholeQueue()) { - inc_running(); - continue; - } - // must be last... invariant is that everything is fully // scavenged at this point. if (traverseWeakPtrList()) { // returns rtsTrue if evaced something @@ -416,12 +408,19 @@ SET_GCT(gc_threads[0]); shutdown_gc_threads(n_gc_threads, gct->thread_index); - // Update pointers from the Task list - update_task_list(); - // Now see which stable names are still alive. gcStablePtrTable(); +#ifdef THREADED_RTS + if (n_gc_threads == 1) { + for (n = 0; n < n_capabilities; n++) { + pruneSparkQueue(&capabilities[n]); + } + } else { + pruneSparkQueue(&capabilities[gct->thread_index]); + } +#endif + #ifdef PROFILING // We call processHeapClosureForDead() on every closure destroyed during // the current garbage collection, so we invoke LdvCensusForDead(). @@ -649,6 +648,7 @@ SET_GCT(gc_threads[0]); freeChain(gen->large_objects); gen->large_objects = gen->scavenged_large_objects; gen->n_large_blocks = gen->n_scavenged_large_blocks; + gen->n_new_large_blocks = 0; ASSERT(countBlocks(gen->large_objects) == gen->n_large_blocks); } else // for generations > N @@ -735,7 +735,6 @@ SET_GCT(gc_threads[0]); // 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. @@ -1000,6 +999,9 @@ any_work (void) #endif gct->no_work++; +#if defined(THREADED_RTS) + yieldThread(); +#endif return rtsFalse; } @@ -1011,7 +1013,7 @@ scavenge_until_all_done (void) loop: - traceEvent(&capabilities[gct->thread_index], EVENT_GC_WORK); + traceEventGcWork(&capabilities[gct->thread_index]); #if defined(THREADED_RTS) if (n_gc_threads > 1) { @@ -1026,7 +1028,7 @@ loop: // scavenge_loop() only exits when there's no work to do r = dec_running(); - traceEvent(&capabilities[gct->thread_index], EVENT_GC_IDLE); + traceEventGcIdle(&capabilities[gct->thread_index]); debugTrace(DEBUG_gc, "%d GC threads still running", r); @@ -1042,7 +1044,7 @@ loop: // scavenge_loop() to perform any pending work. } - traceEvent(&capabilities[gct->thread_index], EVENT_GC_DONE); + traceEventGcDone(&capabilities[gct->thread_index]); } #if defined(THREADED_RTS) @@ -1080,6 +1082,16 @@ gcWorkerThread (Capability *cap) scavenge_until_all_done(); +#ifdef THREADED_RTS + // Now that the whole heap is marked, we discard any sparks that + // were found to be unreachable. The main GC thread is currently + // marking heap reachable via weak pointers, so it is + // non-deterministic whether a spark will be retained if it is + // only reachable via weak pointers. To fix this problem would + // require another GC barrier, which is too high a price. + pruneSparkQueue(cap); +#endif + #ifdef USE_PAPI // count events in this thread towards the GC totals papi_thread_stop_gc1_count(gct->papi_events); @@ -1103,8 +1115,8 @@ gcWorkerThread (Capability *cap) void waitForGcThreads (Capability *cap USED_IF_THREADS) { - nat n_threads = RtsFlags.ParFlags.nNodes; - nat me = cap->no; + const nat n_threads = RtsFlags.ParFlags.nNodes; + const nat me = cap->no; nat i, j; rtsBool retry = rtsTrue; @@ -1178,8 +1190,8 @@ shutdown_gc_threads (nat n_threads USED_IF_THREADS, nat me USED_IF_THREADS) void releaseGCThreads (Capability *cap USED_IF_THREADS) { - nat n_threads = RtsFlags.ParFlags.nNodes; - nat me = cap->no; + const nat n_threads = RtsFlags.ParFlags.nNodes; + const nat me = cap->no; nat i; for (i=0; i < n_threads; i++) { if (i == me) continue; @@ -1451,39 +1463,6 @@ zero_static_object_list(StgClosure* first_static) } /* ---------------------------------------------------------------------------- - Update the pointers from the task list - - These are treated as weak pointers because we want to allow a main - thread to get a BlockedOnDeadMVar exception in the same way as any - other thread. Note that the threads should all have been retained - by GC by virtue of being on the all_threads list, we're just - updating pointers here. - ------------------------------------------------------------------------- */ - -static void -update_task_list (void) -{ - Task *task; - StgTSO *tso; - for (task = all_tasks; task != NULL; task = task->all_link) { - if (!task->stopped && task->tso) { - ASSERT(task->tso->bound == task); - tso = (StgTSO *) isAlive((StgClosure *)task->tso); - if (tso == NULL) { - barf("task %p: main thread %d has been GC'd", -#ifdef THREADED_RTS - (void *)task->id, -#else - (void *)task, -#endif - task->tso->id); - } - task->tso = tso; - } - } -} - -/* ---------------------------------------------------------------------------- Reset the sizes of the older generations when we do a major collection. @@ -1499,8 +1478,8 @@ resize_generations (void) if (major_gc && RtsFlags.GcFlags.generations > 1) { nat live, size, min_alloc, words; - nat max = RtsFlags.GcFlags.maxHeapSize; - nat gens = RtsFlags.GcFlags.generations; + const nat max = RtsFlags.GcFlags.maxHeapSize; + const nat gens = RtsFlags.GcFlags.generations; // live in the oldest generations if (oldest_gen->live_estimate != 0) { @@ -1525,11 +1504,10 @@ resize_generations (void) // Auto-enable compaction when the residency reaches a // certain percentage of the maximum heap size (default: 30%). - if (RtsFlags.GcFlags.generations > 1 && - (RtsFlags.GcFlags.compact || - (max > 0 && - oldest_gen->n_blocks > - (RtsFlags.GcFlags.compactThreshold * max) / 100))) { + if (RtsFlags.GcFlags.compact || + (max > 0 && + oldest_gen->n_blocks > + (RtsFlags.GcFlags.compactThreshold * max) / 100)) { oldest_gen->mark = 1; oldest_gen->compact = 1; // debugBelch("compaction: on\n", live); @@ -1589,7 +1567,7 @@ resize_generations (void) static void resize_nursery (void) { - lnat min_nursery = RtsFlags.GcFlags.minAllocAreaSize * n_capabilities; + const lnat min_nursery = RtsFlags.GcFlags.minAllocAreaSize * n_capabilities; if (RtsFlags.GcFlags.generations == 1) { // Two-space collector: @@ -1649,7 +1627,7 @@ resize_nursery (void) if (RtsFlags.GcFlags.heapSizeSuggestion) { long blocks; - nat needed = calcNeeded(); // approx blocks needed at next GC + const nat needed = calcNeeded(); // approx blocks needed at next GC /* Guess how much will be live in generation 0 step 0 next time. * A good approximation is obtained by finding the