X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FCapability.h;h=dcab3510383345d1bc750085c1cf2bcf3c7a90be;hb=bfb041829d38b711d7f5f783b1ed944f01c23a9b;hp=b559dcd2dc790db23d8a953fefe568272c4a7d13;hpb=9348149e3cfbda59690c6c6f16dd38008f0fa59d;p=ghc-hetmet.git diff --git a/ghc/rts/Capability.h b/ghc/rts/Capability.h index b559dcd..dcab351 100644 --- a/ghc/rts/Capability.h +++ b/ghc/rts/Capability.h @@ -60,6 +60,12 @@ struct Capability_ { // this list. Task *suspended_ccalling_tasks; + // One mutable list per generation, so we don't need to take any + // locks when updating an old-generation thunk. These + // mini-mut-lists are moved onto the respective gen->mut_list at + // each GC. + bdescr **mut_lists; + #if defined(THREADED_RTS) // Worker Tasks waiting in the wings. Singly-linked. Task *spare_workers; @@ -75,18 +81,37 @@ struct Capability_ { Task *returning_tasks_hd; // Singly-linked, with head/tail Task *returning_tasks_tl; #endif + + // Per-capability STM-related data + StgTVarWaitQueue *free_tvar_wait_queues; + StgTRecChunk *free_trec_chunks; + StgTRecHeader *free_trec_headers; + nat transaction_tokens; }; // typedef Capability, defined in RtsAPI.h +#if defined(THREADED_RTS) +#define ASSERT_TASK_ID(task) ASSERT(task->id == osThreadId()) +#else +#define ASSERT_TASK_ID(task) /*empty*/ +#endif + // These properties should be true when a Task is holding a Capability -#define ASSERT_CAPABILITY_INVARIANTS(cap,task) \ +#define ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task) \ ASSERT(cap->running_task != NULL && cap->running_task == task); \ ASSERT(task->cap == cap); \ - ASSERT(cap->run_queue_hd == END_TSO_QUEUE ? \ - cap->run_queue_tl == END_TSO_QUEUE : 1); \ - ASSERT(myTask() == task); \ - ASSERT(task->id == osThreadId()); - + ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task) + +// Sometimes a Task holds a Capability, but the Task is not associated +// with that Capability (ie. task->cap != cap). This happens when +// (a) a Task holds multiple Capabilities, and (b) when the current +// Task is bound, its thread has just blocked, and it may have been +// moved to another Capability. +#define ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task) \ + ASSERT(cap->run_queue_hd == END_TSO_QUEUE ? \ + cap->run_queue_tl == END_TSO_QUEUE : 1); \ + ASSERT(myTask() == task); \ + ASSERT_TASK_ID(task); // Converts a *StgRegTable into a *Capability. // @@ -141,6 +166,8 @@ extern Capability *last_free_capability; // void waitForReturnCapability (Capability **cap/*in/out*/, Task *task); +INLINE_HEADER void recordMutableCap (StgClosure *p, Capability *cap, nat gen); + #if defined(THREADED_RTS) // Gives up the current capability IFF there is a higher-priority @@ -176,6 +203,10 @@ void prodAllCapabilities (void); // void shutdownCapability (Capability *cap, Task *task); +// Attempt to gain control of a Capability if it is free. +// +rtsBool tryGrabCapability (Capability *cap, Task *task); + #else // !THREADED_RTS // Grab a capability. (Only in the non-threaded RTS; in the threaded @@ -185,4 +216,24 @@ extern void grabCapability (Capability **pCap); #endif /* !THREADED_RTS */ +/* ----------------------------------------------------------------------------- + * INLINE functions... private below here + * -------------------------------------------------------------------------- */ + +INLINE_HEADER void +recordMutableCap (StgClosure *p, Capability *cap, nat gen) +{ + bdescr *bd; + + bd = cap->mut_lists[gen]; + if (bd->free >= bd->start + BLOCK_SIZE_W) { + bdescr *new_bd; + new_bd = allocBlock_lock(); + new_bd->link = bd; + bd = new_bd; + cap->mut_lists[gen] = bd; + } + *bd->free++ = (StgWord)p; +} + #endif /* CAPABILITY_H */