@@ -83,6 +83,7 @@ import Control.Monad.IOSim.Types hiding (SimEvent (SimPOREvent),
8383 Trace (SimPORTrace ))
8484import Control.Monad.IOSim.Types (SimEvent )
8585import System.Random (StdGen , randomR , split )
86+ import Data.Bifunctor (first )
8687
8788--
8889-- Simulation interpreter
@@ -855,31 +856,49 @@ unblockThreads !onlySTM !wakeup !simstate@SimState {runqueue, threads, stdGen} =
855856 (unblocked, simstate {
856857 runqueue = Deque. fromList (shuffledRunqueue ++ rest),
857858 threads = threads',
858- stdGen = stdGen''
859+ stdGen = stdGen'''
859860 })
860861 where
861- ! (shuffledRunqueue, stdGen'') = fisherYatesShuffle stdGen' toShuffle
862- ! ((toShuffle, rest), stdGen') =
863- let runqueueList = Deque. toList $ runqueue <> Deque. fromList unblocked
864- runqueueListLength = max 1 (length runqueueList)
865- (ix, newGen) = randomR (0 , runqueueListLength `div` 2 ) stdGen
866- in (splitAt ix runqueueList, newGen)
867862 -- can only unblock if the thread exists and is blocked (not running)
868- ! unblocked = [ tid
863+ ! timerUnblocked = [ tid
869864 | tid <- wakeup
870865 , case Map. lookup tid threads of
871- Just Thread { threadStatus = ThreadBlocked BlockedOnSTM }
872- -> True
873866 Just Thread { threadStatus = ThreadBlocked _ }
874867 -> not onlySTM
875868 _ -> False
876869 ]
870+
871+ ! stmUnblocked = [ tid
872+ | tid <- wakeup
873+ , case Map. lookup tid threads of
874+ Just Thread { threadStatus = ThreadBlocked BlockedOnSTM }
875+ -> True
876+ _ -> False
877+ ]
878+
879+ ! unblocked = timerUnblocked ++ stmUnblocked
880+
877881 -- and in which case we mark them as now running
878882 ! threads' = List. foldl'
879883 (flip (Map. adjust (\ t -> t { threadStatus = ThreadRunning })))
880884 threads
881885 unblocked
882886
887+ -- Shuffle only 1/5th of the time
888+ ! (shouldShuffle, stdGen') =
889+ first (== 0 ) $ randomR (0 :: Int , 5 ) stdGen
890+
891+ -- Only shuffle at most half of the total runqueue
892+ ! ((toShuffle, rest), stdGen'')
893+ | shouldShuffle =
894+ let runqueueList = Deque. toList $ runqueue <> Deque. fromList unblocked
895+ runqueueListLength = max 1 (length runqueueList)
896+ (ix, newGen) = randomR (0 , runqueueListLength `div` 2 ) stdGen'
897+ in (splitAt ix runqueueList, newGen)
898+ | otherwise = (([] , Deque. toList $ runqueue <> Deque. fromList unblocked), stdGen')
899+
900+ ! (shuffledRunqueue, stdGen''') = fisherYatesShuffle stdGen'' toShuffle
901+
883902 -- Fisher-Yates shuffle implementation
884903 fisherYatesShuffle :: StdGen -> [a ] -> ([a ], StdGen )
885904 fisherYatesShuffle gen [] = ([] , gen)
0 commit comments