X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FCapability.c;h=f3bbefea96bb49020f817fe6cf5ed9c437d325b5;hb=65691f95b3727c277a24ec5f0d5a4058c9a681e2;hp=d08bf233393157a64d2a459c617a21133d005884;hpb=74df0d16d17647ab46344802ed57533d38727479;p=ghc-hetmet.git diff --git a/ghc/rts/Capability.c b/ghc/rts/Capability.c index d08bf23..f3bbefe 100644 --- a/ghc/rts/Capability.c +++ b/ghc/rts/Capability.c @@ -1,6 +1,6 @@ /* --------------------------------------------------------------------------- * - * (c) The GHC Team, 2003-2005 + * (c) The GHC Team, 2003-2006 * * Capabilities * @@ -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 @@ -37,29 +39,15 @@ Capability *capabilities = NULL; // locking, so we don't do that. Capability *last_free_capability; -#ifdef SMP -#define UNUSED_IF_NOT_SMP -#else -#define UNUSED_IF_NOT_SMP STG_UNUSED -#endif - -#ifdef RTS_USER_SIGNALS -#define UNUSED_IF_NOT_THREADS -#else -#define UNUSED_IF_NOT_THREADS STG_UNUSED -#endif - - +#if defined(THREADED_RTS) STATIC_INLINE rtsBool globalWorkToDo (void) { return blackholes_need_checking || interrupted -#if defined(RTS_USER_SIGNALS) - || signals_pending() -#endif ; } +#endif #if defined(THREADED_RTS) STATIC_INLINE rtsBool @@ -74,6 +62,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(); } @@ -152,6 +142,11 @@ initCapability( Capability *cap, nat i ) 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; } /* --------------------------------------------------------------------------- @@ -204,11 +199,10 @@ initCapabilities( void ) #if defined(THREADED_RTS) STATIC_INLINE void -giveCapabilityToTask (Capability *cap, Task *task) +giveCapabilityToTask (Capability *cap USED_IF_DEBUG, 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", @@ -239,7 +233,7 @@ releaseCapability_ (Capability* cap) task = cap->running_task; - ASSERT_CAPABILITY_INVARIANTS(cap,task); + ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task); cap->running_task = NULL; @@ -263,7 +257,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; @@ -287,7 +281,7 @@ releaseCapability_ (Capability* cap) } void -releaseCapability (Capability* cap UNUSED_IF_NOT_THREADS) +releaseCapability (Capability* cap USED_IF_THREADS) { ACQUIRE_LOCK(&cap->lock); releaseCapability_(cap); @@ -295,7 +289,7 @@ releaseCapability (Capability* cap UNUSED_IF_NOT_THREADS) } static void -releaseCapabilityAndQueueWorker (Capability* cap UNUSED_IF_NOT_THREADS) +releaseCapabilityAndQueueWorker (Capability* cap USED_IF_THREADS) { Task *task; @@ -333,8 +327,7 @@ releaseCapabilityAndQueueWorker (Capability* cap UNUSED_IF_NOT_THREADS) * * ------------------------------------------------------------------------- */ void -waitForReturnCapability (Capability **pCap, - Task *task UNUSED_IF_NOT_THREADS) +waitForReturnCapability (Capability **pCap, Task *task) { #if !defined(THREADED_RTS) @@ -407,7 +400,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)); @@ -426,15 +419,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 (;;) { @@ -448,6 +440,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; } @@ -475,7 +468,7 @@ yieldCapability (Capability** pCap, Task *task) *pCap = cap; - ASSERT_CAPABILITY_INVARIANTS(cap,task); + ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task); return; }