X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FCapability.c;h=9b5d81dcadb359e70a132fd4214ceea8955b77d9;hb=63179a7b10069d8f69f5bceef27008c9c7fb0aa8;hp=a6a0f0af3e194c0f1f79d0feb59001a69a7e4cc3;hpb=17a596022d01987d5ffe7db0742aa8db267b8cc3;p=ghc-hetmet.git diff --git a/rts/Capability.c b/rts/Capability.c index a6a0f0a..9b5d81d 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -54,8 +54,8 @@ globalWorkToDo (void) #endif #if defined(THREADED_RTS) -rtsBool -stealWork (Capability *cap) +StgClosure * +findSpark (Capability *cap) { /* use the normal Sparks.h interface (internally modified to enable concurrent stealing) @@ -63,16 +63,27 @@ stealWork (Capability *cap) */ Capability *robbed; StgClosurePtr spark; - rtsBool success = rtsFalse; rtsBool retry; nat i = 0; + // first try to get a spark from our own pool. + // We should be using reclaimSpark(), because it works without + // needing any atomic instructions: + // spark = reclaimSpark(cap->sparks); + // However, measurements show that this makes at least one benchmark + // slower (prsa) and doesn't affect the others. + spark = tryStealSpark(cap); + if (spark != NULL) { + cap->sparks_converted++; + return spark; + } + + if (n_capabilities == 1) { return NULL; } // makes no sense... + debugTrace(DEBUG_sched, "cap %d: Trying to steal work from other capabilities", cap->no); - if (n_capabilities == 1) { return rtsFalse; } // makes no sense... - do { retry = rtsFalse; @@ -86,7 +97,7 @@ stealWork (Capability *cap) if (emptySparkPoolCap(robbed)) // nothing to steal here continue; - spark = tryStealSpark(robbed->sparks); + spark = tryStealSpark(robbed); if (spark == NULL && !emptySparkPoolCap(robbed)) { // we conflicted with another thread while trying to steal; // try again later. @@ -97,16 +108,32 @@ stealWork (Capability *cap) debugTrace(DEBUG_sched, "cap %d: Stole a spark from capability %d", cap->no, robbed->no); - - createSparkThread(cap,spark); - return rtsTrue; + cap->sparks_converted++; + return spark; } // otherwise: no success, try next one } } while (retry); debugTrace(DEBUG_sched, "No sparks stolen"); - return rtsFalse; + return NULL; +} + +// Returns True if any spark pool is non-empty at this moment in time +// The result is only valid for an instant, of course, so in a sense +// is immediately invalid, and should not be relied upon for +// correctness. +rtsBool +anySparks (void) +{ + nat i; + + for (i=0; i < n_capabilities; i++) { + if (!emptySparkPoolCap(&capabilities[i])) { + return rtsTrue; + } + } + return rtsFalse; } #endif @@ -768,7 +795,6 @@ shutdownCapability (Capability *cap, Task *task, rtsBool safe) } debugTrace(DEBUG_sched, "capability %d is stopped.", cap->no); - freeCapability(cap); RELEASE_LOCK(&cap->lock); break; } @@ -806,14 +832,28 @@ tryGrabCapability (Capability *cap, Task *task) #endif /* THREADED_RTS */ -void -freeCapability (Capability *cap) { +static void +freeCapability (Capability *cap) +{ stgFree(cap->mut_lists); #if defined(THREADED_RTS) || defined(PARALLEL_HASKELL) freeSparkPool(cap->sparks); #endif } +void +freeCapabilities (void) +{ +#if defined(THREADED_RTS) + nat i; + for (i=0; i < n_capabilities; i++) { + freeCapability(&capabilities[i]); + } +#else + freeCapability(&MainCapability); +#endif +} + /* --------------------------------------------------------------------------- Mark everything directly reachable from the Capabilities. When using multiple GC threads, each GC thread marks all Capabilities