X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FCapability.c;h=9b5d81dcadb359e70a132fd4214ceea8955b77d9;hb=63179a7b10069d8f69f5bceef27008c9c7fb0aa8;hp=c8103117c93a55a0bfe2d0796f4f813636bac224;hpb=b7ea7671c442a0223f34593dc8a1182b15dde0bf;p=ghc-hetmet.git diff --git a/rts/Capability.c b/rts/Capability.c index c810311..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) @@ -66,12 +66,24 @@ stealWork (Capability *cap) 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; @@ -85,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. @@ -96,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