[project @ 2003-12-15 16:23:54 by simonmar]
authorsimonmar <unknown>
Mon, 15 Dec 2003 16:23:54 +0000 (16:23 +0000)
committersimonmar <unknown>
Mon, 15 Dec 2003 16:23:54 +0000 (16:23 +0000)
Fix a deadlock: an OS thread returning from a C call could enter
grabReturnCapability, grabbing the capability that was in the process
of being passed to another thread via passCapability.  This leads to a
deadlock shortly afterward, because the passCapability flag is still
set, so a normal worker won't pick up the capability when it is
released.

Fix (not sure if this is the best fix, though): don't grab the
capability in grabReturnCapability() if passCapabilty is set.

ghc/rts/Capability.c

index 234962b..dd5d0e7 100644 (file)
@@ -69,6 +69,9 @@ Condition thread_ready_cond = INIT_COND_VAR;
  * Task.startTask() uses its current value.
  */
 nat rts_n_waiting_tasks = 0;
+
+static Condition *passTarget = NULL;
+static rtsBool passingCapability = rtsFalse;
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -245,7 +248,7 @@ grabReturnCapability(Mutex* pMutex, Capability** pCap)
   IF_DEBUG(scheduler, 
           sched_belch("worker: returning; workers waiting: %d",
                       rts_n_waiting_workers));
-  if ( noCapabilities() ) {
+  if ( noCapabilities() || passingCapability ) {
     rts_n_waiting_workers++;
     wakeBlockedWorkerThread();
     context_switch = 1;        // make sure it's our turn soon
@@ -316,9 +319,6 @@ yieldToReturningWorker(Mutex* pMutex, Capability** pCap, Condition* pThreadCond)
  * Post-condition: pMutex is held and *pCap is held by the current thread
  */
  
-static Condition *passTarget = NULL;
-static rtsBool passingCapability = rtsFalse;
 void 
 waitForWorkCapability(Mutex* pMutex, Capability** pCap, Condition* pThreadCond)
 {