- scheduleCheckWakeupThreads(cap);
-
- scheduleCheckBlockedThreads(cap);
-
-#if defined(THREADED_RTS) || defined(PARALLEL_HASKELL)
- /* work distribution in multithreaded and parallel systems
-
- REMARK: IMHO best location for work-stealing as well.
- tests above might yield some new jobs, so no need to steal a
- spark in some cases. I believe the yieldCapability.. above
- should be moved here.
- */
-
-#if defined(PARALLEL_HASKELL)
- /* if messages have been buffered... a NOOP in THREADED_RTS */
- scheduleSendPendingMessages();
-#endif
-
- /* If the run queue is empty,...*/
- if (emptyRunQueue(cap)) {
- /* ...take one of our own sparks and turn it into a thread */
- scheduleActivateSpark(cap);
-
- /* if this did not work, try to steal a spark from someone else */
- if (emptyRunQueue(cap)) {
-#if defined(PARALLEL_HASKELL)
- receivedFinish = scheduleGetRemoteWork(cap);
- continue; // a new round, (hopefully) with new work
- /*
- in GUM, this a) sends out a FISH and returns IF no fish is
- out already
- b) (blocking) awaits and receives messages
-
- in Eden, this is only the blocking receive, as b) in GUM.
-
- in Threaded-RTS, this does plain nothing. Stealing routine
- is inside Capability.c and called from
- yieldCapability() at the very beginning, see REMARK.
- */
-#endif
- }
- } else { /* i.e. run queue was (initially) not empty */
- schedulePushWork(cap,task);
- /* work pushing, currently relevant only for THREADED_RTS:
- (pushes threads, wakes up idle capabilities for stealing) */
- }
-
-#if defined(PARALLEL_HASKELL)
- /* since we perform a blocking receive and continue otherwise,
- either we never reach here or we definitely have work! */
- // from here: non-empty run queue
- ASSERT(!emptyRunQueue(cap));
-
- if (PacketsWaiting()) { /* now process incoming messages, if any
- pending...
-
- CAUTION: scheduleGetRemoteWork called
- above, waits for messages as well! */
- processMessages(cap, &receivedFinish);
- }
-#endif // PARALLEL_HASKELL: non-empty run queue!
-
-#endif /* THREADED_RTS || PARALLEL_HASKELL */