[commit: ghc] ghc-lwc2: Handling corner-cases in resuming schedulers that were blocked on foreign call and blackholes. (cfb7a56)

Sivaramakrishnan Krishnamoorthy Chandrasekaran t-sichan at microsoft.com
Sun May 12 02:28:17 CEST 2013


Repository : http://darcs.haskell.org/ghc.git/

On branch  : ghc-lwc2

https://github.com/ghc/ghc/commit/cfb7a56f658459cc8fed5cc524fdf3bc7951cbe0

>---------------------------------------------------------------

commit cfb7a56f658459cc8fed5cc524fdf3bc7951cbe0
Author: KC Sivaramakrishnan <chandras at cs.purdue.edu>
Date:   Sat May 11 17:37:47 2013 -0400

    Handling corner-cases in resuming schedulers that were blocked on foreign call and blackholes.

>---------------------------------------------------------------

 libraries/base/LwConc/Substrate.hs | 16 +++++++++++-----
 rts/RaiseAsync.c                   | 10 +++++++---
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/libraries/base/LwConc/Substrate.hs b/libraries/base/LwConc/Substrate.hs
index 9147e36..3058a3a 100644
--- a/libraries/base/LwConc/Substrate.hs
+++ b/libraries/base/LwConc/Substrate.hs
@@ -416,7 +416,7 @@ switchTo targetSCont = do
   let (I# intStatus) = getIntFromStatus status
   let SCont targetSCont# = targetSCont
   PTM $ \s ->
-    case (atomicSwitch# targetSCont# intStatus s) of s1 -> (# s1, () #)
+    case (atomicSwitch# targetSCont# intStatus s) of s1 -> (# s1, undefined #)
 
 {-# INLINE getSCont #-}
 getSCont :: PTM SCont
@@ -482,7 +482,6 @@ yieldControlActionRts sc = Exception.catch (atomically $ do
   setSContSwitchReason mySC Completed
   stat <- getSContStatus sc
   case stat of
-
       -- SCont hasn't been unblocked yet. This occurs if the SCont is blocked
       -- on a blackhole, throwTo, RTS MVar, safe foreign call etc,. In such
       -- cases, we are likely to perform yieldControlAction (and give up
@@ -496,10 +495,18 @@ yieldControlActionRts sc = Exception.catch (atomically $ do
       -- sets the SCont status to Yielded.
       SContSwitched Yielded -> return ()
 
-      otherwise -> error "yieldControlAction: Impossible status"
+			-- This is a corner case, but is very well possible. Consider that the
+			-- Scont (sc), was blocked on a foreign call, while its scheduler was
+			-- resumed (See rts/Schedule.c:resumeThread). When sc wakes up it has to
+			-- voluntarily give up control. But sc runs to completion and marks the
+			-- thread it is switching to that is should give up the scheduler (See
+			-- rts/PrimOps.cmm:stg_atomicSwitch). Now, the status of sc is set to
+			-- "SContSwitched Completed". Hence, this branch.
+      otherwise -> return ()
+
   switch <- getYieldControlActionSCont sc
   switch sc) (\e -> do {
-                      hPutStrLn stderr ("ERROR:" ++ show (e::IOException));
+                      debugPrint $ "ERROR:" ++ show (e::IOException);
                       error "LwConc.Substrate.yieldControlActionRTS"
                       })
 
@@ -554,7 +561,6 @@ defaultExceptionHandler :: Exception.SomeException -> IO ()
 defaultExceptionHandler e = do
   s <- getSContIO
   debugPrint ("defaultExceptionHandler: " ++ show s ++ " " ++ show (e::Exception.SomeException))
-  defaultUpcall
   atomically $ do
     setSContStatus s SContKilled
     yca <- getYieldControlAction
diff --git a/rts/RaiseAsync.c b/rts/RaiseAsync.c
index b888c4f..3698935 100644
--- a/rts/RaiseAsync.c
+++ b/rts/RaiseAsync.c
@@ -188,7 +188,7 @@ findLastUpdateFrame (StgTSO* tso) {
  * RETURN:
  *
  *  - rtsTrue       if blackhole owner is on current capability and we
- *                  successfully suspended.
+ *                  successfully suspended, or the blackhole has been updated.
  *  - rtsFalse      otherwise
  *---------------------------------------------------------------------------- */
 
@@ -200,9 +200,13 @@ suspendAllComputation (Capability *cap, StgClosure* bh) {
     bh = UNTAG_CLOSURE (bh);
     owner = blackHoleOwner (bh);
 
+    if (owner == NULL)
+      return rtsTrue;
+
     if (owner->cap != cap)
         return rtsFalse;
-    ASSERT (owner->why_blocked != NotBlocked);
+    ASSERT (cap->r.rCurrentTSO->is_upcall_thread ||
+            owner->why_blocked != NotBlocked);
 
     stop_here = findLastUpdateFrame (owner);
     ASSERT (stop_here);
@@ -210,9 +214,9 @@ suspendAllComputation (Capability *cap, StgClosure* bh) {
         barf ("suspendAllComputation: cannot find update frame\n");
     }
 
-    suspendComputationIncluding (cap, owner, stop_here);
     debugTrace (DEBUG_sched, "cap %d: thread %d inheriting work from thread %d",
                 cap->no, cap->r.rCurrentTSO->id, owner->id);
+    suspendComputationIncluding (cap, owner, stop_here);
     return rtsTrue;
 }
 





More information about the ghc-commits mailing list