[project @ 2005-05-05 13:17:47 by simonmar]
[ghc-hetmet.git] / ghc / rts / Capability.c
index 8a93dc9..1e2d3d6 100644 (file)
 #include "OSThreads.h"
 #include "Capability.h"
 #include "Schedule.h"  /* to get at EMPTY_RUN_QUEUE() */
-#include "Signals.h" /* to get at handleSignalsInThisThread() */
 
 #if !defined(SMP)
 Capability MainCapability;     /* for non-SMP, we have one global capability */
 #endif
 
+Capability *capabilities = NULL;
 nat rts_n_free_capabilities;
 
 #if defined(RTS_SUPPORTS_THREADS)
@@ -102,39 +102,11 @@ Capability *free_capabilities;
 static void
 initCapability( Capability *cap )
 {
+    cap->r.rInHaskell      = rtsFalse;
     cap->f.stgGCEnter1     = (F_)__stg_gc_enter_1;
     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)
-{
-  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()
  *
@@ -147,17 +119,31 @@ void
 initCapabilities( void )
 {
 #if defined(SMP)
-  initCapabilities_(RtsFlags.ParFlags.nNodes);
+    nat i,n;
+
+    n = RtsFlags.ParFlags.nNodes;
+    capabilities = stgMallocBytes(n * sizeof(Capability), "initCapabilities");
+
+    for (i = 0; i < n; i++) {
+       initCapability(&capabilities[i]);
+       capabilities[i].link = &capabilities[i+1];
+    }
+    capabilities[n-1].link = NULL;
+    
+    free_capabilities = &capabilities[0];
+    rts_n_free_capabilities = n;
+
+    IF_DEBUG(scheduler, sched_belch("allocated %d capabilities", n));
 #else
-  initCapability(&MainCapability);
+    capabilities = &MainCapability;
+    initCapability(&MainCapability);
+    rts_n_free_capabilities = 1;
 #endif
 
 #if defined(RTS_SUPPORTS_THREADS)
-  initCondition(&returning_worker_cond);
-  initCondition(&thread_ready_cond);
+    initCondition(&returning_worker_cond);
+    initCondition(&thread_ready_cond);
 #endif
-
-  rts_n_free_capabilities = 1;
 }
 
 /* ----------------------------------------------------------------------------
@@ -184,7 +170,6 @@ grabCapability( Capability** cap )
   rts_n_free_capabilities = 0;
 # endif
   *cap = &MainCapability;
-  handleSignalsInThisThread();
 #endif
 #if defined(RTS_SUPPORTS_THREADS)
   IF_DEBUG(scheduler, sched_belch("worker: got capability"));
@@ -207,6 +192,10 @@ releaseCapability( Capability* cap UNUSED_IF_NOT_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) {
@@ -214,12 +203,6 @@ releaseCapability( Capability* cap UNUSED_IF_NOT_SMP )
        // thread that is yielding its capability will repeatedly
        // signal returning_worker_cond.
 
-#if defined(SMP)
-       // SMP variant untested
-       cap->link = free_capabilities;
-       free_capabilities = cap;
-#endif
-
        rts_n_waiting_workers--;
        signalCondition(&returning_worker_cond);
        IF_DEBUG(scheduler, sched_belch("worker: released capability to returning worker"));
@@ -230,17 +213,11 @@ releaseCapability( Capability* cap UNUSED_IF_NOT_SMP )
        } else {
            signalCondition(passTarget);
        }
-       rts_n_free_capabilities = 1;
+       rts_n_free_capabilities++;
        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;
-#endif
        // Signal that a capability is available
        if (rts_n_waiting_tasks > 0 && ANY_WORK_TO_DO()) {
            signalCondition(&thread_ready_cond);
@@ -304,7 +281,6 @@ waitForReturnCapability( Mutex* pMutex, Capability** pCap )
        *pCap = &MainCapability;
        ASSERT(rts_n_free_capabilities == 0);
 #endif
-       handleSignalsInThisThread();
     } else {
        grabCapability(pCap);
     }
@@ -433,7 +409,6 @@ passCapabilityToWorker( void )
    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 )
 {
@@ -444,3 +419,17 @@ threadRunnable ( void )
     startSchedulerTaskIfNecessary();
 #endif
 }
+
+
+/* ----------------------------------------------------------------------------
+   prodWorker()
+
+   Wake up... time to die.
+   -------------------------------------------------------------------------- */
+void
+prodWorker ( void )
+{
+#if defined(RTS_SUPPORTS_THREADS)
+    signalCondition(&thread_ready_cond);
+#endif
+}