#include "RtsFlags.h"
#include "Task.h"
+#include "Sparks.h"
struct Capability_ {
// State required by the STG virtual machine when running Haskell
// 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;
// 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
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)
// 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
//
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.
// 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.
//
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
#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);
+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
{
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;
*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 */