Capability MainCapability; /* for non-SMP, we have one global capability */
#endif
-#if defined(RTS_SUPPORTS_THREADS)
-
nat rts_n_free_capabilities;
+#if defined(RTS_SUPPORTS_THREADS)
+
/* returning_worker_cond: when a worker thread returns from executing an
* external call, it needs to wait for an RTS Capability before passing
* on the result of the call to the Haskell thread that made it.
static rtsBool passingCapability = rtsFalse;
#endif
+#if defined(SMP)
+/*
+ * Free capability list.
+ */
+Capability *free_capabilities;
+#endif
+
#ifdef SMP
#define UNUSED_IF_NOT_SMP
#else
#endif
#if defined(RTS_USER_SIGNALS)
-#define ANY_WORK_TO_DO() (!EMPTY_RUN_QUEUE() || interrupted || signals_pending())
+#define ANY_WORK_TO_DO() (!EMPTY_RUN_QUEUE() || interrupted || blackholes_need_checking || signals_pending())
#else
-#define ANY_WORK_TO_DO() (!EMPTY_RUN_QUEUE() || interrupted)
+#define ANY_WORK_TO_DO() (!EMPTY_RUN_QUEUE() || interrupted || blackholes_need_checking)
#endif
/* ----------------------------------------------------------------------------
cap->f.stgGCFun = (F_)__stg_gc_fun;
}
+/* -----------------------------------------------------------------------------
+ * Function: initCapabilities_(nat)
+ *
+ * Purpose: upon startup, allocate and fill in table
+ * holding 'n' Capabilities. Only for SMP, since
+ * it is the only build that supports multiple
+ * capabilities within the RTS.
+ * -------------------------------------------------------------------------- */
#if defined(SMP)
-static void initCapabilities_(nat n);
-#endif
+static void
+initCapabilities_(nat n)
+{
+ nat i;
+ Capability *cap, *prev;
+ cap = NULL;
+ prev = NULL;
+ for (i = 0; i < n; i++) {
+ cap = stgMallocBytes(sizeof(Capability), "initCapabilities");
+ initCapability(cap);
+ cap->link = prev;
+ prev = cap;
+ }
+ free_capabilities = cap;
+ rts_n_free_capabilities = n;
+ IF_DEBUG(scheduler,
+ sched_belch("allocated %d capabilities", rts_n_free_capabilities));
+}
+#endif /* SMP */
/* ---------------------------------------------------------------------------
* Function: initCapabilities()
#if defined(RTS_SUPPORTS_THREADS)
initCondition(&returning_worker_cond);
initCondition(&thread_ready_cond);
- rts_n_free_capabilities = 1;
#endif
- return;
+ rts_n_free_capabilities = 1;
}
-#if defined(SMP)
-/* Free capability list. */
-static Capability *free_capabilities; /* Available capabilities for running threads */
-static Capability *returning_capabilities;
- /* Capabilities being passed to returning worker threads */
-#endif
-
/* ----------------------------------------------------------------------------
grabCapability( Capability** )
void
grabCapability( Capability** cap )
{
-#if !defined(SMP)
-#if defined(RTS_SUPPORTS_THREADS)
+#if defined(SMP)
+ ASSERT(rts_n_free_capabilities > 0);
+ *cap = free_capabilities;
+ free_capabilities = (*cap)->link;
+ rts_n_free_capabilities--;
+#else
+# if defined(RTS_SUPPORTS_THREADS)
ASSERT(rts_n_free_capabilities == 1);
rts_n_free_capabilities = 0;
-#endif
+# endif
*cap = &MainCapability;
handleSignalsInThisThread();
-#else
- *cap = free_capabilities;
- free_capabilities = (*cap)->link;
- rts_n_free_capabilities--;
#endif
#if defined(RTS_SUPPORTS_THREADS)
IF_DEBUG(scheduler, sched_belch("worker: got capability"));
{
// Precondition: sched_mutex is held.
#if defined(RTS_SUPPORTS_THREADS)
-#ifndef SMP
+#if !defined(SMP)
ASSERT(rts_n_free_capabilities == 0);
#endif
+#if defined(SMP)
+ cap->link = free_capabilities;
+ free_capabilities = cap;
+#endif
// Check to see whether a worker thread can be given
// the go-ahead to return the result of an external call..
if (rts_n_waiting_workers > 0) {
// thread that is yielding its capability will repeatedly
// signal returning_worker_cond.
-#if defined(SMP)
- // SMP variant untested
- cap->link = returning_capabilities;
- returning_capabilities = cap;
-#endif
-
rts_n_waiting_workers--;
signalCondition(&returning_worker_cond);
IF_DEBUG(scheduler, sched_belch("worker: released capability to returning worker"));
} else {
signalCondition(passTarget);
}
+#if defined(SMP)
+ rts_n_free_capabilities++;
+#else
rts_n_free_capabilities = 1;
+#endif
IF_DEBUG(scheduler, sched_belch("worker: released capability, passing it"));
} else {
#if defined(SMP)
- cap->link = free_capabilities;
- free_capabilities = cap;
rts_n_free_capabilities++;
#else
rts_n_free_capabilities = 1;
context_switch = 1; // make sure it's our turn soon
waitCondition(&returning_worker_cond, pMutex);
#if defined(SMP)
- *pCap = returning_capabilities;
- returning_capabilities = (*pCap)->link;
+ *pCap = free_capabilities;
+ free_capabilities = (*pCap)->link;
+ ASSERT(pCap != NULL);
#else
*pCap = &MainCapability;
ASSERT(rts_n_free_capabilities == 0);
- handleSignalsInThisThread();
#endif
+ handleSignalsInThisThread();
} else {
grabCapability(pCap);
}
*pCap = NULL;
}
- // Post-condition: pMutex is assumed held, and either:
+ // Post-condition: either:
//
// 1. *pCap is NULL, in which case the current thread does not
// hold a capability now, or
ToDo: should check whether the thread at the front of the queue is
bound, and if so wake up the appropriate worker.
-------------------------------------------------------------------------- */
-
void
threadRunnable ( void )
{
#endif
}
-/* ------------------------------------------------------------------------- */
-#if defined(SMP)
-/*
- * Function: initCapabilities_(nat)
- *
- * Purpose: upon startup, allocate and fill in table
- * holding 'n' Capabilities. Only for SMP, since
- * it is the only build that supports multiple
- * capabilities within the RTS.
- */
-static void
-initCapabilities_(nat n)
+/* ----------------------------------------------------------------------------
+ prodWorker()
+
+ Wake up... time to die.
+ -------------------------------------------------------------------------- */
+void
+prodWorker ( void )
{
- nat i;
- Capability *cap, *prev;
- cap = NULL;
- prev = NULL;
- for (i = 0; i < n; i++) {
- cap = stgMallocBytes(sizeof(Capability), "initCapabilities");
- initCapability(cap);
- cap->link = prev;
- prev = cap;
- }
- free_capabilities = cap;
- rts_n_free_capabilities = n;
- returning_capabilities = NULL;
- IF_DEBUG(scheduler,
- sched_belch("allocated %d capabilities", n_free_capabilities));
+#if defined(RTS_SUPPORTS_THREADS)
+ signalCondition(&thread_ready_cond);
+#endif
}
-#endif /* SMP */
-