@@ -83,6 +83,7 @@ import Control.Monad.IOSim.Types hiding (SimEvent (SimPOREvent),
83
83
Trace (SimPORTrace ))
84
84
import Control.Monad.IOSim.Types (SimEvent )
85
85
import System.Random (StdGen , randomR , split )
86
+ import Data.Bifunctor (first )
86
87
87
88
--
88
89
-- Simulation interpreter
@@ -855,31 +856,49 @@ unblockThreads !onlySTM !wakeup !simstate@SimState {runqueue, threads, stdGen} =
855
856
(unblocked, simstate {
856
857
runqueue = Deque. fromList (shuffledRunqueue ++ rest),
857
858
threads = threads',
858
- stdGen = stdGen''
859
+ stdGen = stdGen'''
859
860
})
860
861
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)
867
862
-- can only unblock if the thread exists and is blocked (not running)
868
- ! unblocked = [ tid
863
+ ! timerUnblocked = [ tid
869
864
| tid <- wakeup
870
865
, case Map. lookup tid threads of
871
- Just Thread { threadStatus = ThreadBlocked BlockedOnSTM }
872
- -> True
873
866
Just Thread { threadStatus = ThreadBlocked _ }
874
867
-> not onlySTM
875
868
_ -> False
876
869
]
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
+
877
881
-- and in which case we mark them as now running
878
882
! threads' = List. foldl'
879
883
(flip (Map. adjust (\ t -> t { threadStatus = ThreadRunning })))
880
884
threads
881
885
unblocked
882
886
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
+
883
902
-- Fisher-Yates shuffle implementation
884
903
fisherYatesShuffle :: StdGen -> [a ] -> ([a ], StdGen )
885
904
fisherYatesShuffle gen [] = ([] , gen)
0 commit comments