[commit: ghc] ghc-lwc2: Disabled migration of threads running a user-level scheduler, without which sieve program seems to deadlock while running on a high core count. Enabling debug messages seems to make the bug disapper (Grr..). The error most probably is in RtsMessaging subsystem. Needs a different/better testcase. (2fa44a8)

Sivaramakrishnan Krishnamoorthy Chandrasekaran t-sichan at microsoft.com
Tue Apr 30 02:16:25 CEST 2013


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

On branch  : ghc-lwc2

https://github.com/ghc/ghc/commit/2fa44a8ab9d6c68c14ccb25ac26a556d1d82d70d

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

commit 2fa44a8ab9d6c68c14ccb25ac26a556d1d82d70d
Author: KC Sivaramakrishnan <chandras at cs.purdue.edu>
Date:   Mon Apr 29 20:04:28 2013 -0400

    Disabled migration of threads running a user-level scheduler, without
    which sieve program seems to deadlock while running on a high core
    count. Enabling debug messages seems to make the bug disapper (Grr..).
    The error most probably is in RtsMessaging subsystem. Needs a
    different/better testcase.

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

 rts/PrimOps.cmm                          |  3 ++-
 rts/STM.c                                |  0
 rts/Schedule.c                           |  7 +++++--
 tests/Benchmarks/Sieve/ConcurrentList.hs | 12 ++++++------
 tests/Benchmarks/Sieve/Makefile          |  2 +-
 tests/Benchmarks/Sieve/sieve-TMVar.hs    |  6 ++++--
 tests/Benchmarks/Sieve/sieve-lwc.hs      |  1 +
 7 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index 850fef9..d5cc41c 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -633,7 +633,7 @@ again: MAYBE_GC(again);
       	}
 			}
     }
-  } )
+  })
 
   #endif
 
@@ -887,6 +887,7 @@ stg_sleepCapabilityzh ()
 {
 	IF_DEBUG (scheduler,
 		ccall debugBelch ("stg_sleepCapability: thread %d\n", StgTSO_id(CurrentTSO)));
+  ASSERT (StgTSO_is_sleeping (CurrentTSO) == 0::I32);
   StgTSO_is_sleeping (CurrentTSO) = 1::I32;
   jump stg_retryzh [];
 }
diff --git a/rts/Schedule.c b/rts/Schedule.c
index a626ef7..1bebbe5 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -523,7 +523,6 @@ run_thread:
         t->saved_winerror = GetLastError();
 #endif
 
-
         if (ret == ThreadBlocked) {
             if (t->why_blocked == BlockedOnBlackHole) {
                 StgTSO *owner = blackHoleOwner(t->block_info.bh->bh);
@@ -835,6 +834,9 @@ schedulePushWork(Capability *cap USED_IF_THREADS,
                 t->_link = END_TSO_QUEUE;
                 if (t->bound == task->incall // don't move my bound thread
                     || t->is_upcall_thread // don't move upcall thread
+                    // XXX the following is inplace to avoid a hard to debug
+                    // deadlock that occurs in sieve-lwc. Should be fixed!
+                    || hasHaskellScheduler(t) //don't move user-level schedulers
                     || tsoLocked(t)) {  // don't move a locked thread
                     setTSOLink(cap, prev, t);
                     setTSOPrev(cap, t, prev);
@@ -958,7 +960,8 @@ scheduleResumeBlockedOnForeignCall(Capability *cap USED_IF_THREADS)
     //Safely work
     ACQUIRE_LOCK (&cap->lock);
     incall = cap->suspended_ccalls_hd;
-    if (rtsFalse && //XXX disable
+    if (rtsFalse && //XXX KC: disabled! causes an IOError (Bad address) on
+                    //sieve-TMVar.hs. Should be fixed!
         incall && //incall is not NULL
         incall->uls_stat == UserLevelSchedulerBlocked) {
 
diff --git a/tests/Benchmarks/Sieve/ConcurrentList.hs b/tests/Benchmarks/Sieve/ConcurrentList.hs
index 6de9fc3..741bf55 100644
--- a/tests/Benchmarks/Sieve/ConcurrentList.hs
+++ b/tests/Benchmarks/Sieve/ConcurrentList.hs
@@ -44,10 +44,10 @@ newtype Sched = Sched (Array Int (PVar [SCont], PVar [SCont]))
 
 _INL_(yieldControlAction)
 yieldControlAction :: Sched -> PTM ()
-yieldControlAction (Sched pa) = do
+yieldControlAction !(Sched pa) = do
   -- Fetch current capability's scheduler
   cc <- getCurrentCapability
-  let (frontRef, backRef)= pa ! cc
+  let !(frontRef, backRef)= pa ! cc
   front <- readPVar frontRef
   case front of
     [] -> do
@@ -64,14 +64,14 @@ yieldControlAction (Sched pa) = do
 
 _INL_(scheduleSContAction)
 scheduleSContAction :: Sched -> SCont -> PTM ()
-scheduleSContAction (Sched pa) sc = do
+scheduleSContAction !(Sched pa) !sc = do
   -- Since we are making the given scont runnable, update its status to Yielded.
   setSContSwitchReason sc Yielded
   -- Fetch the given SCont's scheduler.
-  cap <- getSContCapability sc
+  !cap <- getSContCapability sc
   let (_,backRef) = pa ! cap
-  back <- readPVar backRef
-  writePVar backRef $ sc:back
+  !back <- readPVar backRef
+  writePVar backRef $! sc:back
 
 
 _INL_(newSched)
diff --git a/tests/Benchmarks/Sieve/Makefile b/tests/Benchmarks/Sieve/Makefile
index d662f80..dee0445 100644
--- a/tests/Benchmarks/Sieve/Makefile
+++ b/tests/Benchmarks/Sieve/Makefile
@@ -3,7 +3,7 @@ TARGET := sieve-vanilla.bin sieve-lwc.bin sieve-TMVar.bin sieve-vanilla-TMVar.bi
 include ../../config.mk
 
 TOP := ../../../
-GHC_OPTS_EXTRA=-O2 -threaded -XBangPatterns -XCPP -XGeneralizedNewtypeDeriving -funbox-strict-fields -optc-O3
+GHC_OPTS_EXTRA=-O2 -threaded -XBangPatterns -XCPP -XGeneralizedNewtypeDeriving -funbox-strict-fields -eventlog -optc-O3 -debug
 
 PROFILE_FLAGS := -DPROFILE_ENABLED -prof -auto-all -fprof-auto
 
diff --git a/tests/Benchmarks/Sieve/sieve-TMVar.hs b/tests/Benchmarks/Sieve/sieve-TMVar.hs
index a8df0c2..bfbed63 100644
--- a/tests/Benchmarks/Sieve/sieve-TMVar.hs
+++ b/tests/Benchmarks/Sieve/sieve-TMVar.hs
@@ -32,9 +32,10 @@ primeFilter mIn mOut prime = do
 main = do
   initSched
   numArg:_ <- getArgs
-  mIn <- atomically $ newEmptyTMVar
+  let n = read numArg
+  mIn <- newEmptyTMVarIO
   forkIO $ generate mIn
-  out <- replicateM (read numArg) (atomically newEmptyTMVar)
+  out <- replicateM n newEmptyTMVarIO
   foldM_ linkFilter mIn out
 
 -- Take a value from mIn, and call it prime. Then show that prime. Make a new thread that
@@ -44,5 +45,6 @@ linkFilter :: TMVar Int -> TMVar Int -> IO (TMVar Int)
 linkFilter mIn mOut = do
   prime <- atomically $ takeTMVar mIn
   putStrLn $ show prime
+  -- debugPrint $ show prime
   forkIO $ primeFilter mIn mOut prime
   return mOut
diff --git a/tests/Benchmarks/Sieve/sieve-lwc.hs b/tests/Benchmarks/Sieve/sieve-lwc.hs
index 48e12d4..1260ebf 100644
--- a/tests/Benchmarks/Sieve/sieve-lwc.hs
+++ b/tests/Benchmarks/Sieve/sieve-lwc.hs
@@ -20,6 +20,7 @@ primeFilter :: MVar Int -> MVar Int -> Int -> IO ()
 primeFilter mIn mOut prime = do
   forever $ do
     i <- takeMVar mIn
+    yield
     when (i `mod` prime /= 0) (putMVar mOut i)
 
 -- Take the first commandline argument and call it numArg.





More information about the ghc-commits mailing list