-}
-#endif
-
-/* ----------------------------------------------------------------------------
- * Activate spark threads (PARALLEL_HASKELL only)
- * ------------------------------------------------------------------------- */
-
-#if defined(PARALLEL_HASKELL)
-static void
-scheduleActivateSpark(void)
-{
-#if defined(SPARKS)
- ASSERT(emptyRunQueue());
-/* We get here if the run queue is empty and 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.
-*/
-
- /* :-[ no local threads => look out for local sparks */
- /* the spark pool for the current PE */
- pool = &(cap.r.rSparks); // JB: cap = (old) MainCap
- if (advisory_thread_count < RtsFlags.ParFlags.maxThreads &&
- pool->hd < pool->tl) {
- /*
- * ToDo: add GC code check that we really have enough heap afterwards!!
- * Old comment:
- * If we're here (no runnable threads) and we have pending
- * sparks, we must have a space problem. Get enough space
- * to turn one of those pending sparks into a
- * thread...
- */
-
- spark = findSpark(rtsFalse); /* get a spark */
- if (spark != (rtsSpark) NULL) {
- tso = createThreadFromSpark(spark); /* turn the spark into a thread */
- IF_PAR_DEBUG(fish, // schedule,
- debugBelch("==== schedule: Created TSO %d (%p); %d threads active\n",
- tso->id, tso, advisory_thread_count));
-
- if (tso==END_TSO_QUEUE) { /* failed to activate spark->back to loop */
- IF_PAR_DEBUG(fish, // schedule,
- debugBelch("==^^ failed to create thread from spark @ %lx\n",
- spark));
- return rtsFalse; /* failed to generate a thread */
- } /* otherwise fall through & pick-up new tso */
- } else {
- IF_PAR_DEBUG(fish, // schedule,
- debugBelch("==^^ no local sparks (spark pool contains only NFs: %d)\n",
- spark_queue_len(pool)));
- return rtsFalse; /* failed to generate a thread */
- }
- return rtsTrue; /* success in generating a thread */
- } else { /* no more threads permitted or pool empty */
- return rtsFalse; /* failed to generateThread */
- }
-#else
- tso = NULL; // avoid compiler warning only
- return rtsFalse; /* dummy in non-PAR setup */
-#endif // SPARKS
-}
-#endif // PARALLEL_HASKELL
-
-/* ----------------------------------------------------------------------------
- * Get work from a remote node (PARALLEL_HASKELL only)
- * ------------------------------------------------------------------------- */
-
-#if defined(PARALLEL_HASKELL)
-static rtsBool
-scheduleGetRemoteWork(rtsBool *receivedFinish)
-{
- ASSERT(emptyRunQueue());
-
- if (RtsFlags.ParFlags.BufferTime) {
- IF_PAR_DEBUG(verbose,
- debugBelch("...send all pending data,"));
- {
- nat i;
- for (i=1; i<=nPEs; i++)
- sendImmediately(i); // send all messages away immediately
- }
- }
-# ifndef SPARKS
- //++EDEN++ idle() , i.e. send all buffers, wait for work
- // suppress fishing in EDEN... just look for incoming messages
- // (blocking receive)
- IF_PAR_DEBUG(verbose,
- debugBelch("...wait for incoming messages...\n"));
- *receivedFinish = processMessages(); // blocking receive...
-
- // and reenter scheduling loop after having received something
- // (return rtsFalse below)
-
-# else /* activate SPARKS machinery */
-/* We get here, if we have no work, tried to activate a local spark, but still
- have no work. We try to get a remote spark, by sending a FISH message.
- Thread migration should be added here, and triggered when a sequence of
- fishes returns without work. */
- delay = (RtsFlags.ParFlags.fishDelay!=0ll ? RtsFlags.ParFlags.fishDelay : 0ll);
-
- /* =8-[ no local sparks => look for work on other PEs */
- /*
- * We really have absolutely no work. Send out a fish
- * (there may be some out there already), and wait for
- * something to arrive. We clearly can't run any threads
- * until a SCHEDULE or RESUME arrives, and so that's what
- * we're hoping to see. (Of course, we still have to
- * respond to other types of messages.)
- */
- rtsTime now = msTime() /*CURRENT_TIME*/;
- IF_PAR_DEBUG(verbose,
- debugBelch("-- now=%ld\n", now));
- IF_PAR_DEBUG(fish, // verbose,
- if (outstandingFishes < RtsFlags.ParFlags.maxFishes &&
- (last_fish_arrived_at!=0 &&
- last_fish_arrived_at+delay > now)) {
- debugBelch("--$$ <%llu> delaying FISH until %llu (last fish %llu, delay %llu)\n",
- now, last_fish_arrived_at+delay,
- last_fish_arrived_at,
- delay);
- });
-
- if (outstandingFishes < RtsFlags.ParFlags.maxFishes &&
- advisory_thread_count < RtsFlags.ParFlags.maxThreads) { // send a FISH, but when?
- if (last_fish_arrived_at==0 ||
- (last_fish_arrived_at+delay <= now)) { // send FISH now!
- /* outstandingFishes is set in sendFish, processFish;
- avoid flooding system with fishes via delay */
- next_fish_to_send_at = 0;
- } else {
- /* ToDo: this should be done in the main scheduling loop to avoid the
- busy wait here; not so bad if fish delay is very small */
- int iq = 0; // DEBUGGING -- HWL
- next_fish_to_send_at = last_fish_arrived_at+delay; // remember when to send
- /* send a fish when ready, but process messages that arrive in the meantime */
- do {
- if (PacketsWaiting()) {
- iq++; // DEBUGGING
- *receivedFinish = processMessages();
- }
- now = msTime();
- } while (!*receivedFinish || now<next_fish_to_send_at);
- // JB: This means the fish could become obsolete, if we receive
- // work. Better check for work again?
- // last line: while (!receivedFinish || !haveWork || now<...)
- // next line: if (receivedFinish || haveWork )
-
- if (*receivedFinish) // no need to send a FISH if we are finishing anyway
- return rtsFalse; // NB: this will leave scheduler loop
- // immediately after return!
-
- IF_PAR_DEBUG(fish, // verbose,
- debugBelch("--$$ <%llu> sent delayed fish (%d processMessages); active/total threads=%d/%d\n",now,iq,run_queue_len(),advisory_thread_count));
-
- }
-
- // JB: IMHO, this should all be hidden inside sendFish(...)
- /* pe = choosePE();
- sendFish(pe, thisPE, NEW_FISH_AGE, NEW_FISH_HISTORY,
- NEW_FISH_HUNGER);
-
- // Global statistics: count no. of fishes
- if (RtsFlags.ParFlags.ParStats.Global &&
- RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
- globalParStats.tot_fish_mess++;
- }
- */
-
- /* delayed fishes must have been sent by now! */
- next_fish_to_send_at = 0;
- }
-
- *receivedFinish = processMessages();
-# endif /* SPARKS */
-
- return rtsFalse;
- /* NB: this function always returns rtsFalse, meaning the scheduler
- loop continues with the next iteration;
- rationale:
- return code means success in finding work; we enter this function
- if there is no local work, thus have to send a fish which takes
- time until it arrives with work; in the meantime we should process
- messages in the main loop;
- */
-}
-#endif // PARALLEL_HASKELL
-
-/* ----------------------------------------------------------------------------
- * PAR/GRAN: Report stats & debugging info(?)
- * ------------------------------------------------------------------------- */
-
-#if defined(PAR) || defined(GRAN)
-static void
-scheduleGranParReport(void)
-{
- ASSERT(run_queue_hd != END_TSO_QUEUE);
-
- /* Take a thread from the run queue, if we have work */
- POP_RUN_QUEUE(t); // take_off_run_queue(END_TSO_QUEUE);
-
- /* If this TSO has got its outport closed in the meantime,
- * it mustn't be run. Instead, we have to clean it up as if it was finished.
- * It has to be marked as TH_DEAD for this purpose.
- * If it is TH_TERM instead, it is supposed to have finished in the normal way.
-
-JB: TODO: investigate wether state change field could be nuked
- entirely and replaced by the normal tso state (whatnext
- field). All we want to do is to kill tsos from outside.
- */
-
- /* ToDo: write something to the log-file
- if (RTSflags.ParFlags.granSimStats && !sameThread)
- DumpGranEvent(GR_SCHEDULE, RunnableThreadsHd);
-
- CurrentTSO = t;
- */
- /* the spark pool for the current PE */
- pool = &(cap.r.rSparks); // cap = (old) MainCap
-
- IF_DEBUG(scheduler,
- debugBelch("--=^ %d threads, %d sparks on [%#x]\n",
- run_queue_len(), spark_queue_len(pool), CURRENT_PROC));
-
- IF_PAR_DEBUG(fish,
- debugBelch("--=^ %d threads, %d sparks on [%#x]\n",
- run_queue_len(), spark_queue_len(pool), CURRENT_PROC));