X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FSchedule.c;h=a7696ed785e330f1ee5e132836425de975dcfeeb;hb=48d21c1fbdf9cf032a528e19195714229530a632;hp=5cad5b2e9333104dabba5b0bc7948f3bbb7b9831;hpb=03a9ff01812afc81eb5236fd3063cbec44cf469e;p=ghc-hetmet.git diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index 5cad5b2..a7696ed 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -367,10 +367,6 @@ schedule (Capability *initialCapability, Task *task) while (TERMINATION_CONDITION) { - ASSERT(cap->running_task == task); - ASSERT(task->cap == cap); - ASSERT(myTask() == task); - #if defined(GRAN) /* Choose the processor with the next event */ CurrentProc = event->proc; @@ -388,6 +384,10 @@ schedule (Capability *initialCapability, Task *task) yieldCapability(&cap, task); } #endif + + ASSERT(cap->running_task == task); + ASSERT(task->cap == cap); + ASSERT(myTask() == task); // Check whether we have re-entered the RTS from Haskell without // going via suspendThread()/resumeThread (i.e. a 'safe' foreign @@ -408,11 +408,12 @@ schedule (Capability *initialCapability, Task *task) deleteRunQueue(cap); if (shutting_down_scheduler) { IF_DEBUG(scheduler, sched_belch("shutting down")); - if (task->tso) { // we are bound - task->stat = Interrupted; - task->ret = NULL; + // If we are a worker, just exit. If we're a bound thread + // then we will exit below when we've removed our TSO from + // the run queue. + if (task->tso == NULL) { + return cap; } - return cap; } else { IF_DEBUG(scheduler, sched_belch("interrupted")); } @@ -574,32 +575,47 @@ run_thread: recent_activity = ACTIVITY_YES; switch (prev_what_next) { - + case ThreadKilled: case ThreadComplete: /* Thread already finished, return to scheduler. */ ret = ThreadFinished; break; - + case ThreadRunGHC: - ret = StgRun((StgFunPtr) stg_returnToStackTop, &cap->r); + { + StgRegTable *r; + r = StgRun((StgFunPtr) stg_returnToStackTop, &cap->r); + cap = regTableToCapability(r); + ret = r->rRet; break; - + } + case ThreadInterpret: - ret = interpretBCO(cap); + cap = interpretBCO(cap); + ret = cap->r.rRet; break; - + default: - barf("schedule: invalid what_next field"); + barf("schedule: invalid what_next field"); } - // in SMP mode, we might return with a different capability than - // we started with, if the Haskell thread made a foreign call. So - // let's find out what our current Capability is: - cap = task->cap; - cap->in_haskell = rtsFalse; +#ifdef SMP + // If ret is ThreadBlocked, and this Task is bound to the TSO that + // blocked, we are in limbo - the TSO is now owned by whatever it + // is blocked on, and may in fact already have been woken up, + // perhaps even on a different Capability. It may be the case + // that task->cap != cap. We better yield this Capability + // immediately and return to normaility. + if (ret == ThreadBlocked) continue; +#endif + + ASSERT(cap->running_task == task); + ASSERT(task->cap == cap); + ASSERT(myTask() == task); + // The TSO might have moved, eg. if it re-entered the RTS and a GC // happened. So find the new location: t = cap->r.rCurrentTSO;