X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FCapability.h;h=9446a7e7794b06526f898675d8938caacddc84c3;hp=dedd6351b693bebc23ba0f0bac3584e29f2f17d5;hb=b7ea7671c442a0223f34593dc8a1182b15dde0bf;hpb=ed12b7043fa98928f75c289a756fbcef546315f8 diff --git a/rts/Capability.h b/rts/Capability.h index dedd635..9446a7e 100644 --- a/rts/Capability.h +++ b/rts/Capability.h @@ -25,6 +25,7 @@ #include "RtsFlags.h" #include "Task.h" +#include "Sparks.h" struct Capability_ { // State required by the STG virtual machine when running Haskell @@ -66,6 +67,10 @@ struct Capability_ { // each GC. bdescr **mut_lists; + // Context switch flag. We used to have one global flag, now one + // per capability. Locks required : none (conflicts are harmless) + int context_switch; + #if defined(THREADED_RTS) // Worker Tasks waiting in the wings. Singly-linked. Task *spare_workers; @@ -86,6 +91,13 @@ struct Capability_ { // woken up by another Capability. StgTSO *wakeup_queue_hd; StgTSO *wakeup_queue_tl; + + SparkPool *sparks; + + // Stats on spark creation/conversion + nat sparks_created; + nat sparks_converted; + nat sparks_pruned; #endif // Per-capability STM-related data @@ -94,7 +106,10 @@ struct Capability_ { StgTRecChunk *free_trec_chunks; StgTRecHeader *free_trec_headers; nat transaction_tokens; -}; // typedef Capability, defined in RtsAPI.h +} // typedef Capability is defined in RtsAPI.h + // Capabilities are stored in an array, so make sure that adjacent + // Capabilities don't share any cache-lines: + ATTRIBUTE_ALIGNED(64); #if defined(THREADED_RTS) @@ -139,12 +154,16 @@ void initCapabilities (void); // ASSUMES: cap->running_task is the current Task. // #if defined(THREADED_RTS) -void releaseCapability (Capability* cap); -void releaseCapability_ (Capability* cap); // assumes cap->lock is held +void releaseCapability (Capability* cap); +void releaseAndWakeupCapability (Capability* cap); +void releaseCapability_ (Capability* cap, rtsBool always_wakeup); +// assumes cap->lock is held #else // releaseCapability() is empty in non-threaded RTS INLINE_HEADER void releaseCapability (Capability* cap STG_UNUSED) {}; -INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED) {}; +INLINE_HEADER void releaseAndWakeupCapability (Capability* cap STG_UNUSED) {}; +INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED, + rtsBool always_wakeup STG_UNUSED) {}; #endif #if !IN_STG_CODE @@ -162,6 +181,9 @@ extern Capability *capabilities; // extern Capability *last_free_capability; +// GC indicator, in scope for the scheduler +extern volatile StgWord waiting_for_gc; + // Acquires a capability at a return point. If *cap is non-NULL, then // this is taken as a preference for the Capability we wish to // acquire. @@ -199,11 +221,8 @@ void waitForCapability (Task *task, Mutex *mutex, Capability **pCap); // Wakes up a thread on a Capability (probably a different Capability // from the one held by the current Task). // -void wakeupThreadOnCapability (Capability *cap, StgTSO *tso); -void wakeupThreadOnCapability_lock (Capability *cap, StgTSO *tso); - -void migrateThreadToCapability (Capability *cap, StgTSO *tso); -void migrateThreadToCapability_lock (Capability *cap, StgTSO *tso); +void wakeupThreadOnCapability (Capability *my_cap, Capability *other_cap, + StgTSO *tso); // Wakes up a worker thread on just one Capability, used when we // need to service some global event. @@ -217,12 +236,20 @@ void prodAllCapabilities (void); // Waits for a capability to drain of runnable threads and workers, // and then acquires it. Used at shutdown time. // -void shutdownCapability (Capability *cap, Task *task); +void shutdownCapability (Capability *cap, Task *task, rtsBool wait_foreign); // Attempt to gain control of a Capability if it is free. // rtsBool tryGrabCapability (Capability *cap, Task *task); +// Try to steal a spark from other Capabilities +// +rtsBool stealWork (Capability *cap); + +INLINE_HEADER rtsBool emptySparkPoolCap (Capability *cap); +INLINE_HEADER nat sparkPoolSizeCap (Capability *cap); +INLINE_HEADER void discardSparksCap (Capability *cap); + #else // !THREADED_RTS // Grab a capability. (Only in the non-threaded RTS; in the threaded @@ -232,8 +259,17 @@ extern void grabCapability (Capability **pCap); #endif /* !THREADED_RTS */ -// Free a capability on exit -void freeCapability (Capability *cap); +// cause all capabilities to context switch as soon as possible. +void setContextSwitches(void); + +// Free all capabilities +void freeCapabilities (void); + +// FOr the GC: +void markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, + rtsBool prune_sparks); +void markCapabilities (evac_fn evac, void *user); +void traverseSparkQueues (evac_fn evac, void *user); /* ----------------------------------------------------------------------------- * INLINE functions... private below here @@ -244,6 +280,8 @@ recordMutableCap (StgClosure *p, Capability *cap, nat gen) { bdescr *bd; + // We must own this Capability in order to modify its mutable list. + ASSERT(cap->running_task == myTask()); bd = cap->mut_lists[gen]; if (bd->free >= bd->start + BLOCK_SIZE_W) { bdescr *new_bd; @@ -255,4 +293,18 @@ recordMutableCap (StgClosure *p, Capability *cap, nat gen) *bd->free++ = (StgWord)p; } +#if defined(THREADED_RTS) +INLINE_HEADER rtsBool +emptySparkPoolCap (Capability *cap) +{ return looksEmpty(cap->sparks); } + +INLINE_HEADER nat +sparkPoolSizeCap (Capability *cap) +{ return sparkPoolSize(cap->sparks); } + +INLINE_HEADER void +discardSparksCap (Capability *cap) +{ return discardSparks(cap->sparks); } +#endif + #endif /* CAPABILITY_H */