{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ViewPatterns #-}
module Test.DejaFu.SCT.Internal.DPOR where
import Control.Applicative ((<|>))
import Control.DeepSeq (NFData)
import qualified Data.Foldable as F
import Data.Function (on)
import Data.List (nubBy, partition, sortOn)
import Data.List.NonEmpty (toList)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import Data.Maybe (isJust, isNothing, listToMaybe,
maybeToList)
import Data.Sequence (Seq, (|>))
import qualified Data.Sequence as Sq
import Data.Set (Set)
import qualified Data.Set as S
import GHC.Generics (Generic)
import GHC.Stack (HasCallStack)
import Test.DejaFu.Internal
import Test.DejaFu.Schedule (Scheduler(..))
import Test.DejaFu.Types
import Test.DejaFu.Utils (decisionOf, tidOf)
data DPOR = DPOR
{ DPOR -> Set ThreadId
dporRunnable :: Set ThreadId
, DPOR -> Map ThreadId Bool
dporTodo :: Map ThreadId Bool
, DPOR -> Maybe (ThreadId, DPOR)
dporNext :: Maybe (ThreadId, DPOR)
, DPOR -> Set ThreadId
dporDone :: Set ThreadId
, DPOR -> Map ThreadId ThreadAction
dporSleep :: Map ThreadId ThreadAction
, DPOR -> Map ThreadId ThreadAction
dporTaken :: Map ThreadId ThreadAction
} deriving (DPOR -> DPOR -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DPOR -> DPOR -> Bool
$c/= :: DPOR -> DPOR -> Bool
== :: DPOR -> DPOR -> Bool
$c== :: DPOR -> DPOR -> Bool
Eq, Int -> DPOR -> ShowS
[DPOR] -> ShowS
DPOR -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DPOR] -> ShowS
$cshowList :: [DPOR] -> ShowS
show :: DPOR -> String
$cshow :: DPOR -> String
showsPrec :: Int -> DPOR -> ShowS
$cshowsPrec :: Int -> DPOR -> ShowS
Show, forall x. Rep DPOR x -> DPOR
forall x. DPOR -> Rep DPOR x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DPOR x -> DPOR
$cfrom :: forall x. DPOR -> Rep DPOR x
Generic, DPOR -> ()
forall a. (a -> ()) -> NFData a
rnf :: DPOR -> ()
$crnf :: DPOR -> ()
NFData)
validateDPOR :: HasCallStack => DPOR -> DPOR
validateDPOR :: HasCallStack => DPOR -> DPOR
validateDPOR DPOR
dpor
| Bool -> Bool
not (Set ThreadId
todo forall a. Ord a => Set a -> Set a -> Bool
`S.isSubsetOf` Set ThreadId
runnable) = forall a. HasCallStack => String -> a
fatal String
"thread exists in todo set but not runnable set"
| Bool -> Bool
not (Set ThreadId
done forall a. Ord a => Set a -> Set a -> Bool
`S.isSubsetOf` Set ThreadId
runnable) = forall a. HasCallStack => String -> a
fatal String
"thread exists in done set but not runnable set"
| Bool -> Bool
not (Set ThreadId
taken forall a. Ord a => Set a -> Set a -> Bool
`S.isSubsetOf` Set ThreadId
done) = forall a. HasCallStack => String -> a
fatal String
"thread exists in taken set but not done set"
| Bool -> Bool
not (Set ThreadId
todo forall a. Ord a => Set a -> Set a -> Bool
`disjoint` Set ThreadId
done) = forall a. HasCallStack => String -> a
fatal String
"thread exists in both todo set and done set"
| Bool -> Bool
not (forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (forall a. Ord a => a -> Set a -> Bool
`S.member` Set ThreadId
done) Maybe ThreadId
next) = forall a. HasCallStack => String -> a
fatal String
"taken thread does not exist in done set"
| Bool
otherwise = DPOR
dpor
where
done :: Set ThreadId
done = DPOR -> Set ThreadId
dporDone DPOR
dpor
next :: Maybe ThreadId
next = forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor
runnable :: Set ThreadId
runnable = DPOR -> Set ThreadId
dporRunnable DPOR
dpor
taken :: Set ThreadId
taken = forall a. Ord a => [a] -> Set a
S.fromList (forall k a. Map k a -> [k]
M.keys (DPOR -> Map ThreadId ThreadAction
dporTaken DPOR
dpor))
todo :: Set ThreadId
todo = forall a. Ord a => [a] -> Set a
S.fromList (forall k a. Map k a -> [k]
M.keys (DPOR -> Map ThreadId Bool
dporTodo DPOR
dpor))
disjoint :: Set a -> Set a -> Bool
disjoint Set a
s1 Set a
s2 = forall a. Set a -> Bool
S.null (forall a. Ord a => Set a -> Set a -> Set a
S.intersection Set a
s1 Set a
s2)
data BacktrackStep = BacktrackStep
{ BacktrackStep -> ThreadId
bcktThreadid :: ThreadId
, BacktrackStep -> Decision
bcktDecision :: Decision
, BacktrackStep -> ThreadAction
bcktAction :: ThreadAction
, BacktrackStep -> Map ThreadId Lookahead
bcktRunnable :: Map ThreadId Lookahead
, BacktrackStep -> Map ThreadId Bool
bcktBacktracks :: Map ThreadId Bool
, BacktrackStep -> ConcurrencyState
bcktState :: ConcurrencyState
} deriving (BacktrackStep -> BacktrackStep -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BacktrackStep -> BacktrackStep -> Bool
$c/= :: BacktrackStep -> BacktrackStep -> Bool
== :: BacktrackStep -> BacktrackStep -> Bool
$c== :: BacktrackStep -> BacktrackStep -> Bool
Eq, Int -> BacktrackStep -> ShowS
[BacktrackStep] -> ShowS
BacktrackStep -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BacktrackStep] -> ShowS
$cshowList :: [BacktrackStep] -> ShowS
show :: BacktrackStep -> String
$cshow :: BacktrackStep -> String
showsPrec :: Int -> BacktrackStep -> ShowS
$cshowsPrec :: Int -> BacktrackStep -> ShowS
Show, forall x. Rep BacktrackStep x -> BacktrackStep
forall x. BacktrackStep -> Rep BacktrackStep x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BacktrackStep x -> BacktrackStep
$cfrom :: forall x. BacktrackStep -> Rep BacktrackStep x
Generic, BacktrackStep -> ()
forall a. (a -> ()) -> NFData a
rnf :: BacktrackStep -> ()
$crnf :: BacktrackStep -> ()
NFData)
initialState :: [ThreadId] -> DPOR
initialState :: [ThreadId] -> DPOR
initialState [ThreadId]
threads
| ThreadId
initialThread forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ThreadId]
threads = DPOR
{ dporRunnable :: Set ThreadId
dporRunnable = forall a. Ord a => [a] -> Set a
S.fromList [ThreadId]
threads
, dporTodo :: Map ThreadId Bool
dporTodo = forall k a. k -> a -> Map k a
M.singleton ThreadId
initialThread Bool
False
, dporNext :: Maybe (ThreadId, DPOR)
dporNext = forall a. Maybe a
Nothing
, dporDone :: Set ThreadId
dporDone = forall a. Set a
S.empty
, dporSleep :: Map ThreadId ThreadAction
dporSleep = forall k a. Map k a
M.empty
, dporTaken :: Map ThreadId ThreadAction
dporTaken = forall k a. Map k a
M.empty
}
| Bool
otherwise = forall a. HasCallStack => String -> a
fatal String
"initialState" String
"Initial thread is not in initially runnable set"
findSchedulePrefix
:: DPOR
-> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
findSchedulePrefix :: DPOR -> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
findSchedulePrefix DPOR
dpor = case DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor of
Just (ThreadId
tid, DPOR
child) -> ThreadId
-> DPOR -> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
go ThreadId
tid DPOR
child forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
here
Maybe (ThreadId, DPOR)
Nothing -> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
here
where
go :: ThreadId
-> DPOR -> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
go ThreadId
tid DPOR
child = (\([ThreadId]
ts,Bool
c,Map ThreadId ThreadAction
slp) -> (ThreadId
tidforall a. a -> [a] -> [a]
:[ThreadId]
ts,Bool
c,Map ThreadId ThreadAction
slp)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DPOR -> Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
findSchedulePrefix DPOR
child
here :: Maybe ([ThreadId], Bool, Map ThreadId ThreadAction)
here =
let todos :: [([ThreadId], Bool, Map ThreadId ThreadAction)]
todos = [([ThreadId
t], Bool
c, Map ThreadId ThreadAction
sleeps) | (ThreadId
t, Bool
c) <- forall k a. Map k a -> [(k, a)]
M.toList forall a b. (a -> b) -> a -> b
$ DPOR -> Map ThreadId Bool
dporTodo DPOR
dpor]
([([ThreadId], Bool, Map ThreadId ThreadAction)]
best, [([ThreadId], Bool, Map ThreadId ThreadAction)]
worst) = forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\([ThreadId
t],Bool
_,Map ThreadId ThreadAction
_) -> ThreadId
t forall a. Ord a => a -> a -> Bool
>= ThreadId
initialThread) [([ThreadId], Bool, Map ThreadId ThreadAction)]
todos
in forall a. [a] -> Maybe a
listToMaybe [([ThreadId], Bool, Map ThreadId ThreadAction)]
best forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. [a] -> Maybe a
listToMaybe [([ThreadId], Bool, Map ThreadId ThreadAction)]
worst
sleeps :: Map ThreadId ThreadAction
sleeps = DPOR -> Map ThreadId ThreadAction
dporSleep DPOR
dpor forall k a. Ord k => Map k a -> Map k a -> Map k a
`M.union` DPOR -> Map ThreadId ThreadAction
dporTaken DPOR
dpor
incorporateTrace :: HasCallStack
=> Bool
-> MemType
-> Bool
-> Trace
-> ConcurrencyState
-> DPOR
-> DPOR
incorporateTrace :: HasCallStack =>
Bool
-> MemType -> Bool -> Trace -> ConcurrencyState -> DPOR -> DPOR
incorporateTrace Bool
safeIO MemType
memtype Bool
conservative = forall {b}.
ThreadId
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> ConcurrencyState
-> DPOR
-> DPOR
grow ThreadId
initialThread where
grow :: ThreadId
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> ConcurrencyState
-> DPOR
-> DPOR
grow ThreadId
tid trc :: [(Decision, [(ThreadId, b)], ThreadAction)]
trc@((Decision
d, [(ThreadId, b)]
_, ThreadAction
a):[(Decision, [(ThreadId, b)], ThreadAction)]
rest) ConcurrencyState
state DPOR
dpor =
let tid' :: ThreadId
tid' = ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d
state' :: ConcurrencyState
state' = MemType
-> ConcurrencyState -> ThreadId -> ThreadAction -> ConcurrencyState
updateCState MemType
memtype ConcurrencyState
state ThreadId
tid' ThreadAction
a
in case DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor of
Just (ThreadId
t, DPOR
child)
| ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
tid' ->
HasCallStack => DPOR -> DPOR
validateDPOR forall a b. (a -> b) -> a -> b
$ DPOR
dpor { dporNext :: Maybe (ThreadId, DPOR)
dporNext = forall a. a -> Maybe a
Just (ThreadId
tid', ThreadId
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> ConcurrencyState
-> DPOR
-> DPOR
grow ThreadId
tid' [(Decision, [(ThreadId, b)], ThreadAction)]
rest ConcurrencyState
state' DPOR
child) }
| DPOR -> Bool
hasTodos DPOR
child -> forall a. HasCallStack => String -> a
fatal String
"replacing child with todos!"
Maybe (ThreadId, DPOR)
_ -> HasCallStack => DPOR -> DPOR
validateDPOR forall a b. (a -> b) -> a -> b
$
let taken :: Map ThreadId ThreadAction
taken = forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert ThreadId
tid' ThreadAction
a (DPOR -> Map ThreadId ThreadAction
dporTaken DPOR
dpor)
sleep :: Map ThreadId ThreadAction
sleep = DPOR -> Map ThreadId ThreadAction
dporSleep DPOR
dpor forall k a. Ord k => Map k a -> Map k a -> Map k a
`M.union` DPOR -> Map ThreadId ThreadAction
dporTaken DPOR
dpor
in DPOR
dpor { dporTaken :: Map ThreadId ThreadAction
dporTaken = if Bool
conservative then DPOR -> Map ThreadId ThreadAction
dporTaken DPOR
dpor else Map ThreadId ThreadAction
taken
, dporTodo :: Map ThreadId Bool
dporTodo = forall k a. Ord k => k -> Map k a -> Map k a
M.delete ThreadId
tid' (DPOR -> Map ThreadId Bool
dporTodo DPOR
dpor)
, dporNext :: Maybe (ThreadId, DPOR)
dporNext = forall a. a -> Maybe a
Just (ThreadId
tid', forall {b}.
ConcurrencyState
-> ThreadId
-> Map ThreadId ThreadAction
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> DPOR
subtree ConcurrencyState
state' ThreadId
tid' Map ThreadId ThreadAction
sleep [(Decision, [(ThreadId, b)], ThreadAction)]
trc)
, dporDone :: Set ThreadId
dporDone = forall a. Ord a => a -> Set a -> Set a
S.insert ThreadId
tid' (DPOR -> Set ThreadId
dporDone DPOR
dpor)
}
grow ThreadId
_ [(Decision, [(ThreadId, b)], ThreadAction)]
_ ConcurrencyState
_ DPOR
_ = forall a. HasCallStack => String -> a
fatal String
"trace exhausted without reading a to-do point!"
hasTodos :: DPOR -> Bool
hasTodos DPOR
dpor = Bool -> Bool
not (forall k a. Map k a -> Bool
M.null (DPOR -> Map ThreadId Bool
dporTodo DPOR
dpor)) Bool -> Bool -> Bool
|| (case DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor of Just (ThreadId
_, DPOR
dpor') -> DPOR -> Bool
hasTodos DPOR
dpor'; Maybe (ThreadId, DPOR)
_ -> Bool
False)
subtree :: ConcurrencyState
-> ThreadId
-> Map ThreadId ThreadAction
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> DPOR
subtree ConcurrencyState
state ThreadId
tid Map ThreadId ThreadAction
sleep ((Decision
_, [(ThreadId, b)]
_, ThreadAction
a):[(Decision, [(ThreadId, b)], ThreadAction)]
rest) = HasCallStack => DPOR -> DPOR
validateDPOR forall a b. (a -> b) -> a -> b
$
let state' :: ConcurrencyState
state' = MemType
-> ConcurrencyState -> ThreadId -> ThreadAction -> ConcurrencyState
updateCState MemType
memtype ConcurrencyState
state ThreadId
tid ThreadAction
a
sleep' :: Map ThreadId ThreadAction
sleep' = forall k a. (k -> a -> Bool) -> Map k a -> Map k a
M.filterWithKey (\ThreadId
t ThreadAction
a' -> Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> ThreadAction
-> Bool
dependent Bool
safeIO ConcurrencyState
state' ThreadId
tid ThreadAction
a ThreadId
t ThreadAction
a') Map ThreadId ThreadAction
sleep
in DPOR
{ dporRunnable :: Set ThreadId
dporRunnable = forall a. Ord a => [a] -> Set a
S.fromList forall a b. (a -> b) -> a -> b
$ case [(Decision, [(ThreadId, b)], ThreadAction)]
rest of
((Decision
d', [(ThreadId, b)]
runnable, ThreadAction
_):[(Decision, [(ThreadId, b)], ThreadAction)]
_) -> ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d' forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(ThreadId, b)]
runnable
[] -> []
, dporTodo :: Map ThreadId Bool
dporTodo = forall k a. Map k a
M.empty
, dporNext :: Maybe (ThreadId, DPOR)
dporNext = case [(Decision, [(ThreadId, b)], ThreadAction)]
rest of
((Decision
d', [(ThreadId, b)]
_, ThreadAction
_):[(Decision, [(ThreadId, b)], ThreadAction)]
_) ->
let tid' :: ThreadId
tid' = ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d'
in forall a. a -> Maybe a
Just (ThreadId
tid', ConcurrencyState
-> ThreadId
-> Map ThreadId ThreadAction
-> [(Decision, [(ThreadId, b)], ThreadAction)]
-> DPOR
subtree ConcurrencyState
state' ThreadId
tid' Map ThreadId ThreadAction
sleep' [(Decision, [(ThreadId, b)], ThreadAction)]
rest)
[] -> forall a. Maybe a
Nothing
, dporDone :: Set ThreadId
dporDone = case [(Decision, [(ThreadId, b)], ThreadAction)]
rest of
((Decision
d', [(ThreadId, b)]
_, ThreadAction
_):[(Decision, [(ThreadId, b)], ThreadAction)]
_) -> forall a. a -> Set a
S.singleton (ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d')
[] -> forall a. Set a
S.empty
, dporSleep :: Map ThreadId ThreadAction
dporSleep = Map ThreadId ThreadAction
sleep'
, dporTaken :: Map ThreadId ThreadAction
dporTaken = case [(Decision, [(ThreadId, b)], ThreadAction)]
rest of
((Decision
d', [(ThreadId, b)]
_, ThreadAction
a'):[(Decision, [(ThreadId, b)], ThreadAction)]
_) -> forall k a. k -> a -> Map k a
M.singleton (ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d') ThreadAction
a'
[] -> forall k a. Map k a
M.empty
}
subtree ConcurrencyState
_ ThreadId
_ Map ThreadId ThreadAction
_ [(Decision, [(ThreadId, b)], ThreadAction)]
_ = forall a. HasCallStack => String -> a
fatal String
"subtree suffix empty!"
findBacktrackSteps
:: Bool
-> MemType
-> BacktrackFunc
-> Bool
-> ConcurrencyState
-> Seq ([(ThreadId, Lookahead)], [ThreadId])
-> Trace
-> [BacktrackStep]
findBacktrackSteps :: Bool
-> MemType
-> BacktrackFunc
-> Bool
-> ConcurrencyState
-> Seq ([(ThreadId, Lookahead)], [ThreadId])
-> Trace
-> [BacktrackStep]
findBacktrackSteps Bool
safeIO MemType
memtype BacktrackFunc
backtrack Bool
boundKill ConcurrencyState
state0 = forall {b}.
ConcurrencyState
-> Set ThreadId
-> ThreadId
-> [BacktrackStep]
-> [([(ThreadId, Lookahead)], [ThreadId])]
-> [(Decision, b, ThreadAction)]
-> [BacktrackStep]
go ConcurrencyState
state0 forall a. Set a
S.empty ThreadId
initialThread [] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList where
go :: ConcurrencyState
-> Set ThreadId
-> ThreadId
-> [BacktrackStep]
-> [([(ThreadId, Lookahead)], [ThreadId])]
-> [(Decision, b, ThreadAction)]
-> [BacktrackStep]
go ConcurrencyState
state Set ThreadId
allThreads ThreadId
tid [BacktrackStep]
bs (([(ThreadId, Lookahead)]
e,[ThreadId]
i):[([(ThreadId, Lookahead)], [ThreadId])]
is) ((Decision
d,b
_,ThreadAction
a):[(Decision, b, ThreadAction)]
ts) =
let tid' :: ThreadId
tid' = ThreadId -> Decision -> ThreadId
tidOf ThreadId
tid Decision
d
state' :: ConcurrencyState
state' = MemType
-> ConcurrencyState -> ThreadId -> ThreadAction -> ConcurrencyState
updateCState MemType
memtype ConcurrencyState
state ThreadId
tid' ThreadAction
a
this :: BacktrackStep
this = BacktrackStep
{ bcktThreadid :: ThreadId
bcktThreadid = ThreadId
tid'
, bcktDecision :: Decision
bcktDecision = Decision
d
, bcktAction :: ThreadAction
bcktAction = ThreadAction
a
, bcktRunnable :: Map ThreadId Lookahead
bcktRunnable = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(ThreadId, Lookahead)]
e
, bcktBacktracks :: Map ThreadId Bool
bcktBacktracks = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (\ThreadId
i' -> (ThreadId
i', Bool
False)) [ThreadId]
i
, bcktState :: ConcurrencyState
bcktState = ConcurrencyState
state
}
bs' :: [BacktrackStep]
bs' = Bool
-> Set ThreadId
-> [(ThreadId, Lookahead)]
-> [BacktrackStep]
-> [BacktrackStep]
doBacktrack Bool
killsEarly Set ThreadId
allThreads' [(ThreadId, Lookahead)]
e ([BacktrackStep]
bsforall a. [a] -> [a] -> [a]
++[BacktrackStep
this])
runnable :: Set ThreadId
runnable = forall a. Ord a => [a] -> Set a
S.fromList (forall k a. Map k a -> [k]
M.keys forall a b. (a -> b) -> a -> b
$ BacktrackStep -> Map ThreadId Lookahead
bcktRunnable BacktrackStep
this)
allThreads' :: Set ThreadId
allThreads' = Set ThreadId
allThreads forall a. Ord a => Set a -> Set a -> Set a
`S.union` Set ThreadId
runnable
killsEarly :: Bool
killsEarly = forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Decision, b, ThreadAction)]
ts Bool -> Bool -> Bool
&& Bool
boundKill
in ConcurrencyState
-> Set ThreadId
-> ThreadId
-> [BacktrackStep]
-> [([(ThreadId, Lookahead)], [ThreadId])]
-> [(Decision, b, ThreadAction)]
-> [BacktrackStep]
go ConcurrencyState
state' Set ThreadId
allThreads' ThreadId
tid' [BacktrackStep]
bs' [([(ThreadId, Lookahead)], [ThreadId])]
is [(Decision, b, ThreadAction)]
ts
go ConcurrencyState
_ Set ThreadId
_ ThreadId
_ [BacktrackStep]
bs [([(ThreadId, Lookahead)], [ThreadId])]
_ [(Decision, b, ThreadAction)]
_ = [BacktrackStep]
bs
doBacktrack :: Bool
-> Set ThreadId
-> [(ThreadId, Lookahead)]
-> [BacktrackStep]
-> [BacktrackStep]
doBacktrack Bool
killsEarly Set ThreadId
allThreads [(ThreadId, Lookahead)]
enabledThreads [BacktrackStep]
bs =
let tagged :: [(Int, BacktrackStep)]
tagged = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [BacktrackStep]
bs
idxs :: [(Int, Bool, ThreadId)]
idxs = [ (Int
i, Bool
False, ThreadId
u)
| (ThreadId
u, Lookahead
n) <- [(ThreadId, Lookahead)]
enabledThreads
, ThreadId
v <- forall a. Set a -> [a]
S.toList Set ThreadId
allThreads
, ThreadId
u forall a. Eq a => a -> a -> Bool
/= ThreadId
v
, Int
i <- forall a. Maybe a -> [a]
maybeToList (forall {a}.
ThreadId
-> Lookahead -> ThreadId -> [(a, BacktrackStep)] -> Maybe a
findIndex ThreadId
u Lookahead
n ThreadId
v [(Int, BacktrackStep)]
tagged)]
findIndex :: ThreadId
-> Lookahead -> ThreadId -> [(a, BacktrackStep)] -> Maybe a
findIndex ThreadId
u Lookahead
n ThreadId
v = forall {a}. [(a, BacktrackStep)] -> Maybe a
go' where
{-# INLINE go' #-}
go' :: [(a, BacktrackStep)] -> Maybe a
go' ((a
i,BacktrackStep
b):[(a, BacktrackStep)]
rest)
| BacktrackStep -> ThreadId
bcktThreadid BacktrackStep
b forall a. Eq a => a -> a -> Bool
== ThreadId
v Bool -> Bool -> Bool
&& (Bool
killsEarly Bool -> Bool -> Bool
|| BacktrackStep -> Bool
isDependent BacktrackStep
b) = forall a. a -> Maybe a
Just a
i
| Bool
otherwise = [(a, BacktrackStep)] -> Maybe a
go' [(a, BacktrackStep)]
rest
go' [] = forall a. Maybe a
Nothing
{-# INLINE isDependent #-}
isDependent :: BacktrackStep -> Bool
isDependent BacktrackStep
b
| ThreadAction -> Bool
isBlock (BacktrackStep -> ThreadAction
bcktAction BacktrackStep
b) Bool -> Bool -> Bool
&& ActionType -> Bool
isBarrier (Lookahead -> ActionType
simplifyLookahead Lookahead
n) = Bool
False
| Bool
otherwise = Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> Lookahead
-> Bool
dependent' Bool
safeIO (BacktrackStep -> ConcurrencyState
bcktState BacktrackStep
b) (BacktrackStep -> ThreadId
bcktThreadid BacktrackStep
b) (BacktrackStep -> ThreadAction
bcktAction BacktrackStep
b) ThreadId
u Lookahead
n
in BacktrackFunc
backtrack [BacktrackStep]
bs [(Int, Bool, ThreadId)]
idxs
incorporateBacktrackSteps :: HasCallStack
=> [BacktrackStep] -> DPOR -> DPOR
incorporateBacktrackSteps :: HasCallStack => [BacktrackStep] -> DPOR -> DPOR
incorporateBacktrackSteps (BacktrackStep
b:[BacktrackStep]
bs) DPOR
dpor = HasCallStack => DPOR -> DPOR
validateDPOR DPOR
dpor' where
tid :: ThreadId
tid = BacktrackStep -> ThreadId
bcktThreadid BacktrackStep
b
dpor' :: DPOR
dpor' = DPOR
dpor
{ dporTodo :: Map ThreadId Bool
dporTodo = DPOR -> Map ThreadId Bool
dporTodo DPOR
dpor forall k a. Ord k => Map k a -> Map k a -> Map k a
`M.union` forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(ThreadId, Bool)]
todo
, dporNext :: Maybe (ThreadId, DPOR)
dporNext = forall a. a -> Maybe a
Just (ThreadId
tid, DPOR
child)
}
todo :: [(ThreadId, Bool)]
todo =
[ (ThreadId, Bool)
x
| x :: (ThreadId, Bool)
x@(ThreadId
t,Bool
c) <- forall k a. Map k a -> [(k, a)]
M.toList forall a b. (a -> b) -> a -> b
$ BacktrackStep -> Map ThreadId Bool
bcktBacktracks BacktrackStep
b
, forall a. a -> Maybe a
Just ThreadId
t forall a. Eq a => a -> a -> Bool
/= (forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor)
, forall a. Ord a => a -> Set a -> Bool
S.notMember ThreadId
t (DPOR -> Set ThreadId
dporDone DPOR
dpor)
, Bool
c Bool -> Bool -> Bool
|| forall k a. Ord k => k -> Map k a -> Bool
M.notMember ThreadId
t (DPOR -> Map ThreadId ThreadAction
dporSleep DPOR
dpor)
]
child :: DPOR
child = case DPOR -> Maybe (ThreadId, DPOR)
dporNext DPOR
dpor of
Just (ThreadId
t, DPOR
d)
| ThreadId
t forall a. Eq a => a -> a -> Bool
/= ThreadId
tid -> forall a. HasCallStack => String -> a
fatal String
"incorporating wrong trace!"
| Bool
otherwise -> HasCallStack => [BacktrackStep] -> DPOR -> DPOR
incorporateBacktrackSteps [BacktrackStep]
bs DPOR
d
Maybe (ThreadId, DPOR)
Nothing -> forall a. HasCallStack => String -> a
fatal String
"child is missing!"
incorporateBacktrackSteps [] DPOR
dpor = DPOR
dpor
data DPORSchedState k = DPORSchedState
{ forall k. DPORSchedState k -> Map ThreadId ThreadAction
schedSleep :: Map ThreadId ThreadAction
, forall k. DPORSchedState k -> [ThreadId]
schedPrefix :: [ThreadId]
, forall k.
DPORSchedState k -> Seq ([(ThreadId, Lookahead)], [ThreadId])
schedBPoints :: Seq ([(ThreadId, Lookahead)], [ThreadId])
, forall k. DPORSchedState k -> Bool
schedIgnore :: Bool
, forall k. DPORSchedState k -> Bool
schedBoundKill :: Bool
, forall k. DPORSchedState k -> ConcurrencyState
schedCState :: ConcurrencyState
, forall k. DPORSchedState k -> Maybe k
schedBState :: Maybe k
} deriving (DPORSchedState k -> DPORSchedState k -> Bool
forall k. Eq k => DPORSchedState k -> DPORSchedState k -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DPORSchedState k -> DPORSchedState k -> Bool
$c/= :: forall k. Eq k => DPORSchedState k -> DPORSchedState k -> Bool
== :: DPORSchedState k -> DPORSchedState k -> Bool
$c== :: forall k. Eq k => DPORSchedState k -> DPORSchedState k -> Bool
Eq, Int -> DPORSchedState k -> ShowS
forall k. Show k => Int -> DPORSchedState k -> ShowS
forall k. Show k => [DPORSchedState k] -> ShowS
forall k. Show k => DPORSchedState k -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DPORSchedState k] -> ShowS
$cshowList :: forall k. Show k => [DPORSchedState k] -> ShowS
show :: DPORSchedState k -> String
$cshow :: forall k. Show k => DPORSchedState k -> String
showsPrec :: Int -> DPORSchedState k -> ShowS
$cshowsPrec :: forall k. Show k => Int -> DPORSchedState k -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall k x. Rep (DPORSchedState k) x -> DPORSchedState k
forall k x. DPORSchedState k -> Rep (DPORSchedState k) x
$cto :: forall k x. Rep (DPORSchedState k) x -> DPORSchedState k
$cfrom :: forall k x. DPORSchedState k -> Rep (DPORSchedState k) x
Generic, forall k. NFData k => DPORSchedState k -> ()
forall a. (a -> ()) -> NFData a
rnf :: DPORSchedState k -> ()
$crnf :: forall k. NFData k => DPORSchedState k -> ()
NFData)
initialDPORSchedState :: Map ThreadId ThreadAction
-> [ThreadId]
-> ConcurrencyState
-> DPORSchedState k
initialDPORSchedState :: forall k.
Map ThreadId ThreadAction
-> [ThreadId] -> ConcurrencyState -> DPORSchedState k
initialDPORSchedState Map ThreadId ThreadAction
sleep [ThreadId]
prefix ConcurrencyState
state0 = DPORSchedState
{ schedSleep :: Map ThreadId ThreadAction
schedSleep = Map ThreadId ThreadAction
sleep
, schedPrefix :: [ThreadId]
schedPrefix = [ThreadId]
prefix
, schedBPoints :: Seq ([(ThreadId, Lookahead)], [ThreadId])
schedBPoints = forall a. Seq a
Sq.empty
, schedIgnore :: Bool
schedIgnore = Bool
False
, schedBoundKill :: Bool
schedBoundKill = Bool
False
, schedCState :: ConcurrencyState
schedCState = ConcurrencyState
state0
, schedBState :: Maybe k
schedBState = forall a. Maybe a
Nothing
}
type IncrementalBoundFunc k
= Maybe k -> Maybe (ThreadId, ThreadAction) -> (Decision, Lookahead) -> Maybe k
type BacktrackFunc
= [BacktrackStep] -> [(Int, Bool, ThreadId)] -> [BacktrackStep]
backtrackAt :: HasCallStack
=> (ThreadId -> BacktrackStep -> Bool)
-> BacktrackFunc
backtrackAt :: HasCallStack =>
(ThreadId -> BacktrackStep -> Bool) -> BacktrackFunc
backtrackAt ThreadId -> BacktrackStep -> Bool
toAll [BacktrackStep]
bs0 = forall {t}.
(Eq t, Num t) =>
[(t, Bool, ThreadId)] -> [BacktrackStep]
backtrackAt' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall {a} {b} {c}. (a, b, c) -> a
fst') forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn forall {a} {b} {c}. (a, b, c) -> a
fst' where
fst' :: (a, b, c) -> a
fst' (a
x,b
_,c
_) = a
x
backtrackAt' :: [(t, Bool, ThreadId)] -> [BacktrackStep]
backtrackAt' ((t
i,Bool
c,ThreadId
t):[(t, Bool, ThreadId)]
is) = forall {t}.
(Eq t, Num t) =>
t
-> [BacktrackStep]
-> t
-> Bool
-> ThreadId
-> [(t, Bool, ThreadId)]
-> [BacktrackStep]
go t
i [BacktrackStep]
bs0 t
i Bool
c ThreadId
t [(t, Bool, ThreadId)]
is
backtrackAt' [] = [BacktrackStep]
bs0
go :: t
-> [BacktrackStep]
-> t
-> Bool
-> ThreadId
-> [(t, Bool, ThreadId)]
-> [BacktrackStep]
go t
i0 (BacktrackStep
b:[BacktrackStep]
bs) t
0 Bool
c ThreadId
tid [(t, Bool, ThreadId)]
is
| Bool -> Bool
not (ThreadId -> BacktrackStep -> Bool
toAll ThreadId
tid BacktrackStep
b) Bool -> Bool -> Bool
&& ThreadId
tid forall k a. Ord k => k -> Map k a -> Bool
`M.member` BacktrackStep -> Map ThreadId Lookahead
bcktRunnable BacktrackStep
b =
let val :: Maybe Bool
val = forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ThreadId
tid forall a b. (a -> b) -> a -> b
$ BacktrackStep -> Map ThreadId Bool
bcktBacktracks BacktrackStep
b
b' :: BacktrackStep
b' = if forall a. Maybe a -> Bool
isNothing Maybe Bool
val Bool -> Bool -> Bool
|| (Maybe Bool
val forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just Bool
False Bool -> Bool -> Bool
&& Bool
c)
then BacktrackStep
b { bcktBacktracks :: Map ThreadId Bool
bcktBacktracks = ThreadId -> Bool -> BacktrackStep -> Map ThreadId Bool
backtrackTo ThreadId
tid Bool
c BacktrackStep
b }
else BacktrackStep
b
in BacktrackStep
b' forall a. a -> [a] -> [a]
: case [(t, Bool, ThreadId)]
is of
((t
i',Bool
c',ThreadId
t'):[(t, Bool, ThreadId)]
is') -> t
-> [BacktrackStep]
-> t
-> Bool
-> ThreadId
-> [(t, Bool, ThreadId)]
-> [BacktrackStep]
go t
i' [BacktrackStep]
bs (t
i'forall a. Num a => a -> a -> a
-t
i0forall a. Num a => a -> a -> a
-t
1) Bool
c' ThreadId
t' [(t, Bool, ThreadId)]
is'
[] -> [BacktrackStep]
bs
| Bool
otherwise =
let b' :: BacktrackStep
b' = BacktrackStep
b { bcktBacktracks :: Map ThreadId Bool
bcktBacktracks = forall {b}. b -> BacktrackStep -> Map ThreadId b
backtrackAll Bool
c BacktrackStep
b }
in BacktrackStep
b' forall a. a -> [a] -> [a]
: case [(t, Bool, ThreadId)]
is of
((t
i',Bool
c',ThreadId
t'):[(t, Bool, ThreadId)]
is') -> t
-> [BacktrackStep]
-> t
-> Bool
-> ThreadId
-> [(t, Bool, ThreadId)]
-> [BacktrackStep]
go t
i' [BacktrackStep]
bs (t
i'forall a. Num a => a -> a -> a
-t
i0forall a. Num a => a -> a -> a
-t
1) Bool
c' ThreadId
t' [(t, Bool, ThreadId)]
is'
[] -> [BacktrackStep]
bs
go t
i0 (BacktrackStep
b:[BacktrackStep]
bs) t
i Bool
c ThreadId
tid [(t, Bool, ThreadId)]
is = BacktrackStep
b forall a. a -> [a] -> [a]
: t
-> [BacktrackStep]
-> t
-> Bool
-> ThreadId
-> [(t, Bool, ThreadId)]
-> [BacktrackStep]
go t
i0 [BacktrackStep]
bs (t
iforall a. Num a => a -> a -> a
-t
1) Bool
c ThreadId
tid [(t, Bool, ThreadId)]
is
go t
_ [] t
_ Bool
_ ThreadId
_ [(t, Bool, ThreadId)]
_ = forall a. HasCallStack => String -> a
fatal String
"ran out of schedule whilst backtracking!"
backtrackTo :: ThreadId -> Bool -> BacktrackStep -> Map ThreadId Bool
backtrackTo ThreadId
tid Bool
c = forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert ThreadId
tid Bool
c forall b c a. (b -> c) -> (a -> b) -> a -> c
. BacktrackStep -> Map ThreadId Bool
bcktBacktracks
backtrackAll :: b -> BacktrackStep -> Map ThreadId b
backtrackAll b
c = forall a b k. (a -> b) -> Map k a -> Map k b
M.map (forall a b. a -> b -> a
const b
c) forall b c a. (b -> c) -> (a -> b) -> a -> c
. BacktrackStep -> Map ThreadId Lookahead
bcktRunnable
dporSched :: HasCallStack
=> Bool
-> IncrementalBoundFunc k
-> Scheduler (DPORSchedState k)
dporSched :: forall k.
HasCallStack =>
Bool -> IncrementalBoundFunc k -> Scheduler (DPORSchedState k)
dporSched Bool
safeIO IncrementalBoundFunc k
boundf = forall state.
(Maybe (ThreadId, ThreadAction)
-> NonEmpty (ThreadId, Lookahead)
-> ConcurrencyState
-> state
-> (Maybe ThreadId, state))
-> Scheduler state
Scheduler forall a b. (a -> b) -> a -> b
$ \Maybe (ThreadId, ThreadAction)
prior NonEmpty (ThreadId, Lookahead)
threads ConcurrencyState
cstate DPORSchedState k
s ->
let
nextState :: [ThreadId] -> DPORSchedState k
nextState [ThreadId]
rest = DPORSchedState k
s
{ schedBPoints :: Seq ([(ThreadId, Lookahead)], [ThreadId])
schedBPoints = forall k.
DPORSchedState k -> Seq ([(ThreadId, Lookahead)], [ThreadId])
schedBPoints DPORSchedState k
s forall a. Seq a -> a -> Seq a
|> (forall {a}. (a -> ThreadId) -> [a] -> [a]
restrictToBound forall a b. (a, b) -> a
fst [(ThreadId, Lookahead)]
threads', [ThreadId]
rest)
, schedCState :: ConcurrencyState
schedCState = ConcurrencyState
cstate
}
initialise :: [ThreadId]
initialise = [ThreadId] -> [ThreadId]
tryDaemons forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ThreadId] -> [ThreadId]
yieldsToEnd forall a b. (a -> b) -> a -> b
$ case Maybe (ThreadId, ThreadAction)
prior of
Just (ThreadId
tid, ThreadAction
act)
| Bool -> Bool
not (ThreadAction -> Bool
didYield ThreadAction
act) Bool -> Bool -> Bool
&& ThreadId
tid forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ThreadId]
tids Bool -> Bool -> Bool
&& ThreadId -> Bool
isInBound ThreadId
tid -> [ThreadId
tid]
Maybe (ThreadId, ThreadAction)
_ -> [ThreadId]
tids
tryDaemons :: [ThreadId] -> [ThreadId]
tryDaemons [ThreadId]
ts
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ThreadId -> Bool
doesKill [ThreadId]
ts = case forall a. (a -> Bool) -> [a] -> ([a], [a])
partition ThreadId -> Bool
doesKill [ThreadId]
tids of
([ThreadId]
kills, [ThreadId]
nokills) -> [ThreadId]
nokills forall a. [a] -> [a] -> [a]
++ [ThreadId]
kills
| Bool
otherwise = [ThreadId]
ts
doesKill :: ThreadId -> Bool
doesKill ThreadId
t = ThreadId -> Lookahead -> Bool
killsDaemons ThreadId
t (ThreadId -> Lookahead
action ThreadId
t)
restrictToBound :: (a -> ThreadId) -> [a] -> [a]
restrictToBound a -> ThreadId
f = forall a. (a -> Bool) -> [a] -> [a]
filter (ThreadId -> Bool
isInBound forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ThreadId
f)
isInBound :: ThreadId -> Bool
isInBound ThreadId
t = forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ IncrementalBoundFunc k
boundf (forall k. DPORSchedState k -> Maybe k
schedBState DPORSchedState k
s) Maybe (ThreadId, ThreadAction)
prior (ThreadId -> Decision
decision ThreadId
t, ThreadId -> Lookahead
action ThreadId
t)
yieldsToEnd :: [ThreadId] -> [ThreadId]
yieldsToEnd [ThreadId]
ts = case forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Lookahead -> Bool
willYield forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId -> Lookahead
action) [ThreadId]
ts of
([ThreadId]
yields, [ThreadId]
noyields) -> [ThreadId]
noyields forall a. [a] -> [a] -> [a]
++ [ThreadId]
yields
decision :: ThreadId -> Decision
decision = forall (f :: * -> *).
Foldable f =>
Maybe ThreadId -> f ThreadId -> ThreadId -> Decision
decisionOf (forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (ThreadId, ThreadAction)
prior) (forall a. Ord a => [a] -> Set a
S.fromList [ThreadId]
tids)
action :: ThreadId -> Lookahead
action ThreadId
t = forall a. HasCallStack => Maybe a -> a
efromJust (forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ThreadId
t [(ThreadId, Lookahead)]
threads')
tids :: [ThreadId]
tids = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(ThreadId, Lookahead)]
threads'
threads' :: [(ThreadId, Lookahead)]
threads' = forall a. NonEmpty a -> [a]
toList NonEmpty (ThreadId, Lookahead)
threads
in case forall k. DPORSchedState k -> [ThreadId]
schedPrefix DPORSchedState k
s of
(ThreadId
t:[ThreadId]
ts) ->
let bstate' :: Maybe k
bstate' = IncrementalBoundFunc k
boundf (forall k. DPORSchedState k -> Maybe k
schedBState DPORSchedState k
s) Maybe (ThreadId, ThreadAction)
prior (ThreadId -> Decision
decision ThreadId
t, ThreadId -> Lookahead
action ThreadId
t)
in (forall a. a -> Maybe a
Just ThreadId
t, ([ThreadId] -> DPORSchedState k
nextState []) { schedPrefix :: [ThreadId]
schedPrefix = [ThreadId]
ts, schedBState :: Maybe k
schedBState = Maybe k
bstate' })
[] ->
let choices :: [ThreadId]
choices = forall {a}. (a -> ThreadId) -> [a] -> [a]
restrictToBound forall a. a -> a
id [ThreadId]
initialise
checkDep :: ThreadId -> ThreadAction -> Bool
checkDep ThreadId
t ThreadAction
a = case Maybe (ThreadId, ThreadAction)
prior of
Just (ThreadId
tid, ThreadAction
act) -> Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> ThreadAction
-> Bool
dependent Bool
safeIO (forall k. DPORSchedState k -> ConcurrencyState
schedCState DPORSchedState k
s) ThreadId
tid ThreadAction
act ThreadId
t ThreadAction
a
Maybe (ThreadId, ThreadAction)
Nothing -> Bool
False
ssleep' :: Map ThreadId ThreadAction
ssleep' = forall k a. (k -> a -> Bool) -> Map k a -> Map k a
M.filterWithKey (\ThreadId
t ThreadAction
a -> Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ ThreadId -> ThreadAction -> Bool
checkDep ThreadId
t ThreadAction
a) forall a b. (a -> b) -> a -> b
$ forall k. DPORSchedState k -> Map ThreadId ThreadAction
schedSleep DPORSchedState k
s
choices' :: [ThreadId]
choices' = forall a. (a -> Bool) -> [a] -> [a]
filter (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` forall k a. Map k a -> [k]
M.keys Map ThreadId ThreadAction
ssleep') [ThreadId]
choices
signore' :: Bool
signore' = Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ThreadId]
choices) Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall k a. Map k a -> [k]
M.keys Map ThreadId ThreadAction
ssleep') [ThreadId]
choices
sbkill' :: Bool
sbkill' = Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ThreadId]
initialise) Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ThreadId]
choices
in case [ThreadId]
choices' of
(ThreadId
nextTid:[ThreadId]
rest) ->
let bstate' :: Maybe k
bstate' = IncrementalBoundFunc k
boundf (forall k. DPORSchedState k -> Maybe k
schedBState DPORSchedState k
s) Maybe (ThreadId, ThreadAction)
prior (ThreadId -> Decision
decision ThreadId
nextTid, ThreadId -> Lookahead
action ThreadId
nextTid)
in (forall a. a -> Maybe a
Just ThreadId
nextTid, ([ThreadId] -> DPORSchedState k
nextState [ThreadId]
rest) { schedSleep :: Map ThreadId ThreadAction
schedSleep = Map ThreadId ThreadAction
ssleep', schedBState :: Maybe k
schedBState = Maybe k
bstate' })
[] ->
(forall a. Maybe a
Nothing, ([ThreadId] -> DPORSchedState k
nextState []) { schedIgnore :: Bool
schedIgnore = Bool
signore', schedBoundKill :: Bool
schedBoundKill = Bool
sbkill', schedBState :: Maybe k
schedBState = forall a. Maybe a
Nothing })
independent :: Bool -> ConcurrencyState -> ThreadId -> ThreadAction -> ThreadId -> ThreadAction -> Bool
independent :: Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> ThreadAction
-> Bool
independent Bool
safeIO ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 ThreadId
t2 ThreadAction
a2
| ThreadId
t1 forall a. Eq a => a -> a -> Bool
== ThreadId
t2 = Bool
False
| forall {p}. p -> ThreadAction -> ThreadId -> ThreadAction -> Bool
check ThreadId
t1 ThreadAction
a1 ThreadId
t2 ThreadAction
a2 = Bool
False
| forall {p}. p -> ThreadAction -> ThreadId -> ThreadAction -> Bool
check ThreadId
t2 ThreadAction
a2 ThreadId
t1 ThreadAction
a1 = Bool
False
| Bool
otherwise = Bool -> Bool
not (Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> ThreadAction
-> Bool
dependent Bool
safeIO ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 ThreadId
t2 ThreadAction
a2)
where
check :: p -> ThreadAction -> ThreadId -> ThreadAction -> Bool
check p
_ (Fork ThreadId
t) ThreadId
tid ThreadAction
_ | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
tid = Bool
True
check p
_ (ForkOS ThreadId
t) ThreadId
tid ThreadAction
_ | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
tid = Bool
True
check p
_ (ThrowTo ThreadId
t Maybe MaskingState
_) ThreadId
tid ThreadAction
_ | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
tid = Bool
True
check p
_ (BlockedThrowTo ThreadId
t) ThreadId
tid ThreadAction
_ | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
tid = Bool
True
check p
_ (ThreadAction -> ActionType
simplifyAction -> UnsynchronisedWrite IORefId
r) ThreadId
_ (ThreadAction -> ActionType
simplifyAction -> ActionType
a) | ActionType -> IORefId -> Bool
synchronises ActionType
a IORefId
r = Bool
True
check p
_ ThreadAction
_ ThreadId
_ ThreadAction
_ = Bool
False
dependent :: Bool -> ConcurrencyState -> ThreadId -> ThreadAction -> ThreadId -> ThreadAction -> Bool
dependent :: Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> ThreadAction
-> Bool
dependent Bool
safeIO ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 ThreadId
t2 ThreadAction
a2 = case (ThreadAction
a1, ThreadAction
a2) of
(ThrowTo ThreadId
t Maybe MaskingState
_, ThrowTo ThreadId
u Maybe MaskingState
_)
| ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t2 Bool -> Bool -> Bool
&& ThreadId
u forall a. Eq a => a -> a -> Bool
== ThreadId
t1 -> ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 Bool -> Bool -> Bool
|| ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t2 ThreadAction
a2
(ThrowTo ThreadId
t Maybe MaskingState
_, ThreadAction
_) | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t2 -> ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t2 ThreadAction
a2 Bool -> Bool -> Bool
&& ThreadAction
a2 forall a. Eq a => a -> a -> Bool
/= ThreadAction
Stop
(ThreadAction
_, ThrowTo ThreadId
t Maybe MaskingState
_) | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t1 -> ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 Bool -> Bool -> Bool
&& ThreadAction
a1 forall a. Eq a => a -> a -> Bool
/= ThreadAction
Stop
(STM [TAction]
_ [ThreadId]
_, STM [TAction]
_ [ThreadId]
_) -> Bool
checkSTM
(STM [TAction]
_ [ThreadId]
_, BlockedSTM [TAction]
_) -> Bool
checkSTM
(STM [TAction]
_ [ThreadId]
_, ThrownSTM [TAction]
_ Maybe MaskingState
_) -> Bool
checkSTM
(BlockedSTM [TAction]
_, STM [TAction]
_ [ThreadId]
_) -> Bool
checkSTM
(BlockedSTM [TAction]
_, BlockedSTM [TAction]
_) -> Bool
checkSTM
(BlockedSTM [TAction]
_, ThrownSTM [TAction]
_ Maybe MaskingState
_) -> Bool
checkSTM
(ThrownSTM [TAction]
_ Maybe MaskingState
_, STM [TAction]
_ [ThreadId]
_) -> Bool
checkSTM
(ThrownSTM [TAction]
_ Maybe MaskingState
_, BlockedSTM [TAction]
_) -> Bool
checkSTM
(ThrownSTM [TAction]
_ Maybe MaskingState
_, ThrownSTM [TAction]
_ Maybe MaskingState
_) -> Bool
checkSTM
(ThreadAction, ThreadAction)
_ -> Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> Lookahead
-> Bool
dependent' Bool
safeIO ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 ThreadId
t2 (ThreadAction -> Lookahead
rewind ThreadAction
a2)
Bool -> Bool -> Bool
&& Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> Lookahead
-> Bool
dependent' Bool
safeIO ConcurrencyState
ds ThreadId
t2 ThreadAction
a2 ThreadId
t1 (ThreadAction -> Lookahead
rewind ThreadAction
a1)
where
checkSTM :: Bool
checkSTM = ThreadAction -> ThreadAction -> Bool
checkSTM' ThreadAction
a1 ThreadAction
a2 Bool -> Bool -> Bool
|| ThreadAction -> ThreadAction -> Bool
checkSTM' ThreadAction
a2 ThreadAction
a1
checkSTM' :: ThreadAction -> ThreadAction -> Bool
checkSTM' ThreadAction
a ThreadAction
b = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Set a -> Bool
S.null forall a b. (a -> b) -> a -> b
$ ThreadAction -> Set TVarId
tvarsWritten ThreadAction
a forall a. Ord a => Set a -> Set a -> Set a
`S.intersection` ThreadAction -> Set TVarId
tvarsOf ThreadAction
b
dependent' :: Bool -> ConcurrencyState -> ThreadId -> ThreadAction -> ThreadId -> Lookahead -> Bool
dependent' :: Bool
-> ConcurrencyState
-> ThreadId
-> ThreadAction
-> ThreadId
-> Lookahead
-> Bool
dependent' Bool
safeIO ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 ThreadId
t2 Lookahead
l2 = case (ThreadAction
a1, Lookahead
l2) of
(ThreadAction
LiftIO, Lookahead
WillLiftIO) -> Bool -> Bool
not Bool
safeIO
(ThrowTo ThreadId
t Maybe MaskingState
_, WillThrowTo ThreadId
u)
| ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t2 Bool -> Bool -> Bool
&& ThreadId
u forall a. Eq a => a -> a -> Bool
== ThreadId
t1 -> ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 Bool -> Bool -> Bool
|| ConcurrencyState -> ThreadId -> Lookahead -> Bool
canInterruptL ConcurrencyState
ds ThreadId
t2 Lookahead
l2
(ThrowTo ThreadId
t Maybe MaskingState
_, Lookahead
_) | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t2 -> ConcurrencyState -> ThreadId -> Lookahead -> Bool
canInterruptL ConcurrencyState
ds ThreadId
t2 Lookahead
l2 Bool -> Bool -> Bool
&& Lookahead
l2 forall a. Eq a => a -> a -> Bool
/= Lookahead
WillStop
(ThreadAction
_, WillThrowTo ThreadId
t) | ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
t1 -> ConcurrencyState -> ThreadId -> ThreadAction -> Bool
canInterrupt ConcurrencyState
ds ThreadId
t1 ThreadAction
a1 Bool -> Bool -> Bool
&& ThreadAction
a1 forall a. Eq a => a -> a -> Bool
/= ThreadAction
Stop
(STM [TAction]
_ [ThreadId]
_, Lookahead
WillSTM) -> Bool
True
(BlockedSTM [TAction]
_, Lookahead
WillSTM) -> Bool
True
(ThrownSTM [TAction]
_ Maybe MaskingState
_, Lookahead
WillSTM) -> Bool
True
(GetNumCapabilities Int
_, WillSetNumCapabilities Int
_) -> Bool
True
(SetNumCapabilities Int
_, Lookahead
WillGetNumCapabilities) -> Bool
True
(SetNumCapabilities Int
_, WillSetNumCapabilities Int
_) -> Bool
True
(ThreadAction, Lookahead)
_ -> ConcurrencyState -> ActionType -> ActionType -> Bool
dependentActions ConcurrencyState
ds (ThreadAction -> ActionType
simplifyAction ThreadAction
a1) (Lookahead -> ActionType
simplifyLookahead Lookahead
l2)
dependentActions :: ConcurrencyState -> ActionType -> ActionType -> Bool
dependentActions :: ConcurrencyState -> ActionType -> ActionType -> Bool
dependentActions ConcurrencyState
ds ActionType
a1 ActionType
a2 = case (ActionType
a1, ActionType
a2) of
(UnsynchronisedRead IORefId
_, UnsynchronisedRead IORefId
_) -> Bool
False
(UnsynchronisedWrite IORefId
r1, PartiallySynchronisedCommit IORefId
r2) | IORefId
r1 forall a. Eq a => a -> a -> Bool
== IORefId
r2 Bool -> Bool -> Bool
&& ConcurrencyState -> IORefId -> Bool
isBuffered ConcurrencyState
ds IORefId
r1 -> Bool
False
(PartiallySynchronisedCommit IORefId
r1, UnsynchronisedWrite IORefId
r2) | IORefId
r1 forall a. Eq a => a -> a -> Bool
== IORefId
r2 Bool -> Bool -> Bool
&& ConcurrencyState -> IORefId -> Bool
isBuffered ConcurrencyState
ds IORefId
r1 -> Bool
False
(UnsynchronisedRead IORefId
r1, ActionType
_) | ActionType -> Bool
isBarrier ActionType
a2 Bool -> Bool -> Bool
&& ConcurrencyState -> IORefId -> Bool
isBuffered ConcurrencyState
ds IORefId
r1 -> Bool
True
(ActionType
_, UnsynchronisedRead IORefId
r2) | ActionType -> Bool
isBarrier ActionType
a1 Bool -> Bool -> Bool
&& ConcurrencyState -> IORefId -> Bool
isBuffered ConcurrencyState
ds IORefId
r2 -> Bool
True
(PartiallySynchronisedCommit IORefId
r1, ActionType
_) | ActionType -> IORefId -> Bool
synchronises ActionType
a2 IORefId
r1 -> Bool
True
(ActionType
_, PartiallySynchronisedCommit IORefId
r2) | ActionType -> IORefId -> Bool
synchronises ActionType
a1 IORefId
r2 -> Bool
True
(SynchronisedWrite MVarId
v1, SynchronisedWrite MVarId
v2) | MVarId
v1 forall a. Eq a => a -> a -> Bool
== MVarId
v2 -> Bool -> Bool
not (ConcurrencyState -> MVarId -> Bool
isFull ConcurrencyState
ds MVarId
v1)
(SynchronisedRead MVarId
v1, SynchronisedRead MVarId
v2) | MVarId
v1 forall a. Eq a => a -> a -> Bool
== MVarId
v2 -> ConcurrencyState -> MVarId -> Bool
isFull ConcurrencyState
ds MVarId
v1
(SynchronisedWrite MVarId
v1, SynchronisedRead MVarId
v2) | MVarId
v1 forall a. Eq a => a -> a -> Bool
== MVarId
v2 -> Bool
True
(SynchronisedRead MVarId
v1, SynchronisedWrite MVarId
v2) | MVarId
v1 forall a. Eq a => a -> a -> Bool
== MVarId
v2 -> Bool
True
(ActionType
_, ActionType
_) -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (\IORefId
r -> forall a. a -> Maybe a
Just IORefId
r forall a. Eq a => a -> a -> Bool
== ActionType -> Maybe IORefId
iorefOf ActionType
a2) (ActionType -> Maybe IORefId
iorefOf ActionType
a1)
didYield :: ThreadAction -> Bool
didYield :: ThreadAction -> Bool
didYield ThreadAction
Yield = Bool
True
didYield (ThreadDelay Int
_) = Bool
True
didYield ThreadAction
_ = Bool
False
willYield :: Lookahead -> Bool
willYield :: Lookahead -> Bool
willYield Lookahead
WillYield = Bool
True
willYield (WillThreadDelay Int
_) = Bool
True
willYield Lookahead
_ = Bool
False
killsDaemons :: ThreadId -> Lookahead -> Bool
killsDaemons :: ThreadId -> Lookahead -> Bool
killsDaemons ThreadId
t Lookahead
WillStop = ThreadId
t forall a. Eq a => a -> a -> Bool
== ThreadId
initialThread
killsDaemons ThreadId
_ Lookahead
_ = Bool
False