diff options
author | berthold@mathematik.uni-marburg.de <unknown> | 2008-09-15 13:28:46 +0000 |
---|---|---|
committer | berthold@mathematik.uni-marburg.de <unknown> | 2008-09-15 13:28:46 +0000 |
commit | cf9650f2a1690c04051c716124bb0350adc74ae7 (patch) | |
tree | f2e622b8eea04515fc4a19d24a1ecb57a654b33d /rts/Sparks.h | |
parent | 7eeac4d143e9287d7c2e27ba23b84d175df49962 (diff) | |
download | haskell-cf9650f2a1690c04051c716124bb0350adc74ae7.tar.gz |
Work stealing for sparks
Spark stealing support for PARALLEL_HASKELL and THREADED_RTS versions of the RTS.
Spark pools are per capability, separately allocated and held in the Capability
structure. The implementation uses Double-Ended Queues (deque) and cas-protected
access.
The write end of the queue (position bottom) can only be used with
mutual exclusion, i.e. by exactly one caller at a time.
Multiple readers can steal()/findSpark() from the read end
(position top), and are synchronised without a lock, based on a cas
of the top position. One reader wins, the others return NULL for a
failure.
Work stealing is called when Capabilities find no other work (inside yieldCapability),
and tries all capabilities 0..n-1 twice, unless a theft succeeds.
Inside schedulePushWork, all considered cap.s (those which were idle and could
be grabbed) are woken up. Future versions should wake up capabilities immediately when
putting a new spark in the local pool, from newSpark().
Patch has been re-recorded due to conflicting bugfixes in the sparks.c, also fixing a
(strange) conflict in the scheduler.
Diffstat (limited to 'rts/Sparks.h')
-rw-r--r-- | rts/Sparks.h | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/rts/Sparks.h b/rts/Sparks.h index 8e0ba90f3d..dbbf268988 100644 --- a/rts/Sparks.h +++ b/rts/Sparks.h @@ -9,17 +9,45 @@ #ifndef SPARKS_H #define SPARKS_H +#if defined(PARALLEL_HASKELL) +#error Sparks.c using new internal structure, needs major overhaul! +#endif + +/* typedef for SparkPool in RtsTypes.h */ + #if defined(THREADED_RTS) + +/* INVARIANTS, in this order: bottom/top consistent, reasonable size, + topBound consistent, space pointer, space accessible to us */ +#define ASSERT_SPARK_POOL_INVARIANTS(p) \ + ASSERT((p)->bottom >= (p)->top); \ + ASSERT((p)->size > 0); \ + ASSERT((p)->size > (p)->bottom - (p)->top); \ + ASSERT((p)->topBound <= (p)->top); \ + ASSERT((p)->elements != NULL); \ + ASSERT(*((p)->elements) || 1); \ + ASSERT(*((p)->elements - 1 + ((p)->size)) || 1); + +// missing in old interface. Currently called by initSparkPools +// internally. +SparkPool* initPool(StgWord size); + +// special case: accessing our own pool, at the write end +// otherwise, we can always steal from our pool as the others do... +StgClosure* reclaimSpark(Capability *cap); + +rtsBool looksEmpty(SparkPool* deque); + +// rest: same as old interface StgClosure * findSpark (Capability *cap); void initSparkPools (void); -void freeSparkPool (StgSparkPool *pool); +void freeSparkPool (SparkPool *pool); void createSparkThread (Capability *cap, StgClosure *p); void pruneSparkQueues (void); void traverseSparkQueue(evac_fn evac, void *user, Capability *cap); -INLINE_HEADER void discardSparks (StgSparkPool *pool); -INLINE_HEADER nat sparkPoolSize (StgSparkPool *pool); -INLINE_HEADER rtsBool emptySparkPool (StgSparkPool *pool); +INLINE_HEADER void discardSparks (SparkPool *pool); +INLINE_HEADER nat sparkPoolSize (SparkPool *pool); INLINE_HEADER void discardSparksCap (Capability *cap); INLINE_HEADER nat sparkPoolSizeCap (Capability *cap); @@ -32,46 +60,33 @@ INLINE_HEADER rtsBool emptySparkPoolCap (Capability *cap); #if defined(PARALLEL_HASKELL) || defined(THREADED_RTS) -INLINE_HEADER rtsBool -emptySparkPool (StgSparkPool *pool) -{ - return (pool->hd == pool->tl); -} +INLINE_HEADER rtsBool +emptySparkPool (SparkPool *pool) +{ return looksEmpty(pool); } INLINE_HEADER rtsBool emptySparkPoolCap (Capability *cap) -{ return emptySparkPool(&cap->r.rSparks); } +{ return looksEmpty(cap->sparks); } INLINE_HEADER nat -sparkPoolSize (StgSparkPool *pool) +sparkPoolSize (SparkPool *pool) { - if (pool->hd <= pool->tl) { - return (pool->tl - pool->hd); - } else { - return (pool->lim - pool->hd + pool->tl - pool->base); - } + return (pool->bottom - pool->top); } INLINE_HEADER nat sparkPoolSizeCap (Capability *cap) -{ return sparkPoolSize(&cap->r.rSparks); } +{ return sparkPoolSize(cap->sparks); } INLINE_HEADER void -discardSparks (StgSparkPool *pool) +discardSparks (SparkPool *pool) { - pool->hd = pool->tl; + pool->top = pool->bottom = 0; } INLINE_HEADER void discardSparksCap (Capability *cap) -{ return discardSparks(&cap->r.rSparks); } - - -#elif defined(THREADED_RTS) - -INLINE_HEADER rtsBool -emptySparkPoolCap (Capability *cap STG_UNUSED) -{ return rtsTrue; } +{ return discardSparks(cap->sparks); } #endif |