X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=rts%2FSchedule.c;h=63e2e99f06811d21025caaba7bf63b987a515745;hb=a650cec6aebe5be3706f6aef603bd27a5c0ec1f0;hp=cc5cbb476fe934dfe450f479d34ec8899271d60d;hpb=bd6fe3a37cefc235c5abf08557635031678d65e4;p=ghc-hetmet.git diff --git a/rts/Schedule.c b/rts/Schedule.c index cc5cbb4..63e2e99 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -654,15 +654,9 @@ scheduleFindWork (Capability *cap) scheduleCheckBlockedThreads(cap); #if defined(THREADED_RTS) || defined(PARALLEL_HASKELL) - // Try to activate one of our own sparks if (emptyRunQueue(cap)) { scheduleActivateSpark(cap); } #endif -#if defined(THREADED_RTS) - // Try to steak work if we don't have any - if (emptyRunQueue(cap)) { stealWork(cap); } -#endif - #if defined(PARALLEL_HASKELL) // if messages have been buffered... scheduleSendPendingMessages(); @@ -706,7 +700,9 @@ shouldYieldCapability (Capability *cap, Task *task) // - we need to yield this Capability to someone else // (see shouldYieldCapability()) // -// The return value indicates whether +// Careful: the scheduler loop is quite delicate. Make sure you run +// the tests in testsuite/concurrent (all ways) after modifying this, +// and also check the benchmarks in nofib/parallel for regressions. static void scheduleYield (Capability **pcap, Task *task) @@ -714,7 +710,10 @@ scheduleYield (Capability **pcap, Task *task) Capability *cap = *pcap; // if we have work, and we don't need to give up the Capability, continue. - if (!emptyRunQueue(cap) && !shouldYieldCapability(cap,task)) + if (!shouldYieldCapability(cap,task) && + (!emptyRunQueue(cap) || + blackholes_need_checking || + sched_state >= SCHED_INTERRUPTING)) return; // otherwise yield (sleep), and keep yielding if necessary. @@ -934,8 +933,13 @@ scheduleCheckBlackHoles (Capability *cap) { ACQUIRE_LOCK(&sched_mutex); if ( blackholes_need_checking ) { - checkBlackHoles(cap); blackholes_need_checking = rtsFalse; + // important that we reset the flag *before* checking the + // blackhole queue, otherwise we could get deadlock. This + // happens as follows: we wake up a thread that + // immediately runs on another Capability, blocks on a + // blackhole, and then we reset the blackholes_need_checking flag. + checkBlackHoles(cap); } RELEASE_LOCK(&sched_mutex); } @@ -1063,30 +1067,10 @@ scheduleSendPendingMessages(void) static void scheduleActivateSpark(Capability *cap) { - StgClosure *spark; - -/* We only want to stay here if the run queue is empty and we want some - work. We try to turn a spark into a thread, and add it to the run - queue, from where it will be picked up in the next iteration of the - scheduler loop. -*/ - if (!emptyRunQueue(cap)) - /* In the threaded RTS, another task might have pushed a thread - on our run queue in the meantime ? But would need a lock.. */ - return; - - - // Really we should be using reclaimSpark() here, but - // experimentally it doesn't seem to perform as well as just - // stealing from our own spark pool: - // spark = reclaimSpark(cap->sparks); - spark = tryStealSpark(cap->sparks); // defined in Sparks.c - - if (spark != NULL) { - debugTrace(DEBUG_sched, - "turning spark of closure %p into a thread", - (StgClosure *)spark); - createSparkThread(cap,spark); // defined in Sparks.c + if (anySparks()) + { + createSparkThread(cap); + debugTrace(DEBUG_sched, "creating a spark thread"); } } #endif // PARALLEL_HASKELL || THREADED_RTS @@ -2114,14 +2098,13 @@ exitScheduler( boundTaskExiting(task); stopTaskManager(); } -#else - freeCapability(&MainCapability); #endif } void freeScheduler( void ) { + freeCapabilities(); freeTaskManager(); if (n_capabilities != 1) { stgFree(capabilities);