X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FCapability.c;h=5ca2f518fe0782db77d23cf224e0154ec275208a;hb=c1fa1f507a3cad662618941102ebc6fb87df4dbd;hp=ad3339c3d044fdc3dfc46c90d3a6ad5d1d8f28bb;hpb=9decae3f49f00d1373d1a49951ae3716fd170fec;p=ghc-hetmet.git diff --git a/ghc/rts/Capability.c b/ghc/rts/Capability.c index ad3339c..5ca2f51 100644 --- a/ghc/rts/Capability.c +++ b/ghc/rts/Capability.c @@ -20,9 +20,11 @@ #include "Rts.h" #include "RtsUtils.h" #include "RtsFlags.h" +#include "STM.h" #include "OSThreads.h" #include "Capability.h" #include "Schedule.h" +#include "Sparks.h" #if !defined(SMP) Capability MainCapability; // for non-SMP, we have one global capability @@ -74,6 +76,8 @@ anyWorkForMe( Capability *cap, Task *task ) } else { return (cap->run_queue_hd->bound == task); } + } else if (task->tso == NULL && !emptySparkPoolCap(cap)) { + return rtsTrue; } return globalWorkToDo(); } @@ -125,7 +129,7 @@ popReturningTask (Capability *cap) static void initCapability( Capability *cap, nat i ) { - nat g; + nat g; cap->no = i; cap->in_haskell = rtsFalse; @@ -148,9 +152,15 @@ initCapability( Capability *cap, nat i ) cap->mut_lists = stgMallocBytes(sizeof(bdescr *) * RtsFlags.GcFlags.generations, "initCapability"); - for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - cap->mut_lists[g] = NULL; + + for (g = 0; g < RtsFlags.GcFlags.generations; g++) { + cap->mut_lists[g] = NULL; } + + cap->free_tvar_wait_queues = END_STM_WAIT_QUEUE; + cap->free_trec_chunks = END_STM_CHUNK_LIST; + cap->free_trec_headers = NO_TREC; + cap->transaction_tokens = 0; } /* --------------------------------------------------------------------------- @@ -207,7 +217,6 @@ giveCapabilityToTask (Capability *cap, Task *task) { ASSERT_LOCK_HELD(&cap->lock); ASSERT(task->cap == cap); - // We are not modifying task->cap, so we do not need to take task->lock. IF_DEBUG(scheduler, sched_belch("passing capability %d to %s %p", cap->no, task->tso ? "bound task" : "worker", @@ -238,7 +247,7 @@ releaseCapability_ (Capability* cap) task = cap->running_task; - ASSERT_CAPABILITY_INVARIANTS(cap,task); + ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task); cap->running_task = NULL; @@ -262,7 +271,7 @@ releaseCapability_ (Capability* cap) // If we have an unbound thread on the run queue, or if there's // anything else to do, give the Capability to a worker thread. - if (!emptyRunQueue(cap) || globalWorkToDo()) { + if (!emptyRunQueue(cap) || !emptySparkPoolCap(cap) || globalWorkToDo()) { if (cap->spare_workers) { giveCapabilityToTask(cap,cap->spare_workers); // The worker Task pops itself from the queue; @@ -406,7 +415,7 @@ waitForReturnCapability (Capability **pCap, } - ASSERT_CAPABILITY_INVARIANTS(cap,task); + ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task); IF_DEBUG(scheduler, sched_belch("returning; got capability %d", cap->no)); @@ -425,15 +434,14 @@ yieldCapability (Capability** pCap, Task *task) { Capability *cap = *pCap; - // The fast path; no locking - if ( cap->returning_tasks_hd == NULL && anyWorkForMe(cap,task) ) - return; + // The fast path has no locking, if we don't enter this while loop while ( cap->returning_tasks_hd != NULL || !anyWorkForMe(cap,task) ) { IF_DEBUG(scheduler, sched_belch("giving up capability %d", cap->no)); // We must now release the capability and wait to be woken up // again. + task->wakeup = rtsFalse; releaseCapabilityAndQueueWorker(cap); for (;;) { @@ -447,6 +455,7 @@ yieldCapability (Capability** pCap, Task *task) IF_DEBUG(scheduler, sched_belch("woken up on capability %d", cap->no)); ACQUIRE_LOCK(&cap->lock); if (cap->running_task != NULL) { + IF_DEBUG(scheduler, sched_belch("capability %d is owned by another task", cap->no)); RELEASE_LOCK(&cap->lock); continue; } @@ -474,7 +483,7 @@ yieldCapability (Capability** pCap, Task *task) *pCap = cap; - ASSERT_CAPABILITY_INVARIANTS(cap,task); + ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task); return; }