X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FCapability.c;h=fa7f63069f0b909f758ea18db0beacc207ef08de;hb=a9afdc24b1b2bbe63d71e8e2890770edfa8a6a8d;hp=ffaa372f98abe16f2eecc935c00f09140c73af24;hpb=681aad99cb29ce54f72ec2a916fb1aab0fa0fabb;p=ghc-hetmet.git diff --git a/rts/Capability.c b/rts/Capability.c index ffaa372..fa7f630 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -759,3 +759,77 @@ freeCapability (Capability *cap) { #endif } +/* --------------------------------------------------------------------------- + Mark everything directly reachable from the Capabilities. When + using multiple GC threads, each GC thread marks all Capabilities + for which (c `mod` n == 0), for Capability c and thread n. + ------------------------------------------------------------------------ */ + +void +markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta) +{ + nat i; + Capability *cap; + Task *task; + + // 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 = i0; i < n_capabilities; i += delta) { + cap = &capabilities[i]; + evac(user, (StgClosure **)(void *)&cap->run_queue_hd); + evac(user, (StgClosure **)(void *)&cap->run_queue_tl); +#if defined(THREADED_RTS) + evac(user, (StgClosure **)(void *)&cap->wakeup_queue_hd); + evac(user, (StgClosure **)(void *)&cap->wakeup_queue_tl); +#endif + for (task = cap->suspended_ccalling_tasks; task != NULL; + task=task->next) { + debugTrace(DEBUG_sched, + "evac'ing suspended TSO %lu", (unsigned long)task->suspended_tso->id); + evac(user, (StgClosure **)(void *)&task->suspended_tso); + } + } + +#if !defined(THREADED_RTS) + evac(user, (StgClosure **)(void *)&blocked_queue_hd); + evac(user, (StgClosure **)(void *)&blocked_queue_tl); + evac(user, (StgClosure **)(void *)&sleeping_queue); +#endif +} + +// Sparks are not roots for GC, so we don't mark them in +// markSomeCapabilities(). Instead, we traverse the spark queues +// after GC and throw away any that are unreachable. +void +updateCapabilitiesPostGC (void) +{ +#if defined(THREADED_RTS) + nat i; + for (i = 0; i < n_capabilities; i++) { + updateSparkQueue (&capabilities[i]); + } +#endif // THREADED_RTS +} + +// This function is used by the compacting GC to thread all the +// pointers from spark queues. +void +traverseSparkQueues (evac_fn evac USED_IF_THREADS, void *user USED_IF_THREADS) +{ +#if defined(THREADED_RTS) + nat i; + for (i = 0; i < n_capabilities; i++) { + traverseSparkQueue (evac, user, &capabilities[i]); + } +#endif // THREADED_RTS + +} + +void +markCapabilities (evac_fn evac, void *user) +{ + markSomeCapabilities(evac, user, 0, 1); +}