gct->evac_step = 0;
GetRoots(mark_root);
+#if defined(RTS_USER_SIGNALS)
+ // mark the signal handlers (signals should be already blocked)
+ markSignalHandlers(mark_root);
+#endif
+
// Mark the weak pointer list, and prepare to detect dead weak pointers.
markWeakPtrList();
initWeakForGC();
------------------------------------------------------------------------ */
-/* This has to be protected either by the scheduler monitor, or by the
- garbage collection monitor (probably the latter).
- KH @ 25/10/99
-*/
-
void
GetRoots( evac_fn evac )
{
Capability *cap;
Task *task;
- for (i = 0; i < n_capabilities; i++) {
+ // Each GC thread is responsible for following roots from the
+ // Capability of the same number. There will usually be the same
+ // or fewer Capabilities as GC threads, but just in case there
+ // are more, we mark every Capability whose number is the GC
+ // thread's index plus a multiple of the number of GC threads.
+ for (i = gct->thread_index; i < n_capabilities; i += n_gc_threads) {
cap = &capabilities[i];
evac((StgClosure **)(void *)&cap->run_queue_hd);
evac((StgClosure **)(void *)&cap->run_queue_tl);
evac((StgClosure **)(void *)&task->suspended_tso);
}
+#if defined(THREADED_RTS)
+ markSparkQueue(evac,cap);
+#endif
}
#if !defined(THREADED_RTS)
evac((StgClosure **)(void *)&blocked_queue_tl);
evac((StgClosure **)(void *)&sleeping_queue);
#endif
-
- // evac((StgClosure **)&blackhole_queue);
-
-#if defined(THREADED_RTS)
- markSparkQueue(evac);
-#endif
-
-#if defined(RTS_USER_SIGNALS)
- // mark the signal handlers (signals should be already blocked)
- markSignalHandlers(evac);
-#endif
}
/* -----------------------------------------------------------------------------
// GarbageCollect(), or this is a worker thread and the main
// thread bumped gc_running_threads before waking us up.
+ // Every thread evacuates some roots.
+ gct->evac_step = 0;
+ GetRoots(mark_root);
+
loop:
scavenge_loop();
// scavenge_loop() only exits when there's no work to do
// If the block at the head of the list in this generation
// is less than 3/4 full, then use it as a todo block.
- if (isPartiallyFull(stp->blocks))
+ if (stp->blocks && isPartiallyFull(stp->blocks))
{
ws->todo_bd = stp->blocks;
ws->todo_free = ws->todo_bd->free;