X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FSchedule.c;h=d22d48fb8f2b4e4b0d52092029d9b55cf551ad7e;hb=ea1ad23f58b5e45731b47a1d686c0dd73766e1b7;hp=38e3a3c2ce2d8b27cb28db93895fe1e872ebc3f5;hpb=0bff4d75254dabb2c002eace2252a4480bf8474e;p=ghc-hetmet.git diff --git a/rts/Schedule.c b/rts/Schedule.c index 38e3a3c..d22d48f 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -1402,6 +1402,12 @@ scheduleHandleThreadFinished (Capability *cap STG_UNUSED, Task *task, StgTSO *t) debugTrace(DEBUG_sched, "--++ thread %lu (%s) finished", (unsigned long)t->id, whatNext_strs[t->what_next]); + // blocked exceptions can now complete, even if the thread was in + // blocked mode (see #2910). This unconditionally calls + // lockTSO(), which ensures that we don't miss any threads that + // are engaged in throwTo() with this thread as a target. + awakenBlockedExceptionQueue (cap, t); + // // Check whether the thread that just completed was a bound // thread, and if so return with the result. @@ -1592,6 +1598,21 @@ delete_threads_and_gc: heap_census = scheduleNeedHeapProfile(rtsTrue); + if (recent_activity == ACTIVITY_INACTIVE && force_major) + { + // We are doing a GC because the system has been idle for a + // timeslice and we need to check for deadlock. Record the + // fact that we've done a GC and turn off the timer signal; + // it will get re-enabled if we run any threads after the GC. + // + // Note: this is done before GC, because after GC there might + // be threads already running (GarbageCollect() releases the + // GC threads when it completes), so we risk turning off the + // timer signal when it should really be on. + recent_activity = ACTIVITY_DONE_GC; + stopTimer(); + } + #if defined(THREADED_RTS) debugTrace(DEBUG_sched, "doing GC"); // reset waiting_for_gc *before* GC, so that when the GC threads @@ -1633,16 +1654,6 @@ delete_threads_and_gc: balanceSparkPoolsCaps(n_capabilities, capabilities); #endif - if (force_major) - { - // We've just done a major GC and we don't need the timer - // signal turned on any more (#1623). - // NB. do this *before* releasing the Capabilities, to avoid - // deadlocks! - recent_activity = ACTIVITY_DONE_GC; - stopTimer(); - } - #if defined(THREADED_RTS) if (gc_type == PENDING_GC_SEQ) { // release our stash of capabilities. @@ -1976,7 +1987,10 @@ resumeThread (void *task_) debugTrace(DEBUG_sched, "thread %lu: re-entering RTS", (unsigned long)tso->id); if (tso->why_blocked == BlockedOnCCall) { - awakenBlockedExceptionQueue(cap,tso); + // avoid locking the TSO if we don't have to + if (tso->blocked_exceptions != END_TSO_QUEUE) { + awakenBlockedExceptionQueue(cap,tso); + } tso->flags &= ~(TSO_BLOCKEX | TSO_INTERRUPTIBLE); }