Skip to content

Commit 606ed50

Browse files
committed
io-sim-por: include Effects in the SimTrace
This allows to show more compact information about execution. It's useful for debugging IOSimPOR.
1 parent 776ed44 commit 606ed50

File tree

3 files changed

+75
-28
lines changed

3 files changed

+75
-28
lines changed

io-sim/src/Control/Monad/IOSim/Types.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,10 @@ data SimEventType
10211021
| EventPerformAction StepId
10221022
-- ^ /IOSimPOR/ event: perform action of the given step
10231023
| EventReschedule ScheduleControl
1024+
1025+
| EventEffect VectorClock Effect
1026+
-- ^ /IOSimPOR/ event: executed effect; Useful for debugging IOSimPOR or
1027+
-- showing compact information about thread execution.
10241028
deriving Show
10251029

10261030

io-sim/src/Control/Monad/IOSimPOR/Internal.hs

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,16 @@ schedule thread@Thread{
376376
(Right thread0@Thread { threadMasking = maskst' }, timers'') -> do
377377
-- We found a suitable exception handler, continue with that
378378
-- We record a step, in case there is no exception handler on replay.
379-
let thread' = stepThread thread0
380-
control' = advanceControl (threadStepId thread0) control
381-
races' = updateRacesInSimState thread0 simstate
379+
let (thread', eff) = stepThread thread0
380+
control' = advanceControl (threadStepId thread0) control
381+
races' = updateRacesInSimState thread0 simstate
382382
trace <- schedule thread' simstate{ races = races',
383383
control = control',
384384
timers = timers'' }
385385
return (SimPORTrace time tid tstep tlbl (EventThrow e) $
386-
SimPORTrace time tid tstep tlbl (EventMask maskst') trace)
386+
SimPORTrace time tid tstep tlbl (EventMask maskst') $
387+
SimPORTrace time tid tstep tlbl (EventEffect vClock eff)
388+
trace)
387389

388390
(Left isMain, timers'')
389391
-- We unwound and did not find any suitable exception handler, so we
@@ -809,16 +811,24 @@ threadInterruptible thread =
809811

810812
deschedule :: Deschedule -> Thread s a -> SimState s a -> ST s (SimTrace a)
811813

812-
deschedule Yield thread@Thread { threadId = tid }
813-
simstate@SimState{runqueue, threads, control} =
814+
deschedule Yield thread@Thread { threadId = tid,
815+
threadStep = tstep,
816+
threadLabel = tlbl,
817+
threadVClock = vClock }
818+
simstate@SimState{runqueue,
819+
threads,
820+
curTime = time,
821+
control } =
814822

815823
-- We don't interrupt runnable threads anywhere else.
816824
-- We do it here by inserting the current thread into the runqueue in priority order.
817825

818-
let thread' = stepThread thread
819-
runqueue' = insertThread thread' runqueue
820-
threads' = Map.insert tid thread' threads
821-
control' = advanceControl (threadStepId thread) control in
826+
let (thread', eff) = stepThread thread
827+
runqueue' = insertThread thread' runqueue
828+
threads' = Map.insert tid thread' threads
829+
control' = advanceControl (threadStepId thread) control in
830+
831+
SimPORTrace time tid tstep tlbl (EventEffect vClock eff) <$>
822832
reschedule simstate { runqueue = runqueue',
823833
threads = threads',
824834
races = updateRacesInSimState thread simstate,
@@ -856,11 +866,18 @@ deschedule Interruptable thread@Thread {
856866
, let tlbl'' = lookupThreadLabel tid'' threads ]
857867
trace
858868

859-
deschedule Interruptable thread@Thread{threadId = tid } simstate@SimState{ control } =
869+
deschedule Interruptable thread@Thread{threadId = tid,
870+
threadStep = tstep,
871+
threadLabel = tlbl,
872+
threadVClock = vClock}
873+
simstate@SimState{ control,
874+
curTime = time } =
860875
-- Either masked or unmasked but no pending async exceptions.
861876
-- Either way, just carry on.
862877
-- Record a step, though, in case on replay there is an async exception.
863-
let thread' = stepThread thread in
878+
let (thread', eff) = stepThread thread in
879+
880+
SimPORTrace time tid tstep tlbl (EventEffect vClock eff) <$>
864881
schedule thread'
865882
simstate{ races = updateRacesInSimState thread simstate,
866883
control = advanceControl (threadStepId thread) control }
@@ -876,21 +893,29 @@ deschedule (Blocked _blockedReason) thread@Thread { threadId = tid
876893
-- thread if possible.
877894
deschedule Interruptable thread { threadMasking = Unmasked } simstate
878895

879-
deschedule (Blocked blockedReason) thread@Thread{ threadId = tid, threadEffect = effect } simstate@SimState{threads, control} =
880-
let thread1 = thread { threadStatus = ThreadBlocked blockedReason }
881-
thread' = stepThread thread1
882-
threads' = Map.insert (threadId thread') thread' threads in
896+
deschedule (Blocked blockedReason) thread@Thread{ threadId = tid,
897+
threadStep = tstep,
898+
threadLabel = tlbl,
899+
threadVClock = vClock}
900+
simstate@SimState{ threads,
901+
curTime = time,
902+
control } =
903+
let thread1 = thread { threadStatus = ThreadBlocked blockedReason }
904+
(thread', eff) = stepThread thread1
905+
threads' = Map.insert (threadId thread') thread' threads in
906+
907+
SimPORTrace time tid tstep tlbl (EventEffect vClock eff) <$>
883908
reschedule simstate { threads = threads',
884909
races = updateRacesInSimState thread1 simstate,
885910
control = advanceControl (threadStepId thread1) control }
886911

887-
deschedule Terminated thread@Thread { threadId = tid, threadVClock = vClock, threadEffect = effect }
912+
deschedule Terminated thread@Thread { threadId = tid, threadLabel = tlbl, threadVClock = vClock, threadEffect = effect }
888913
simstate@SimState{ curTime = time, control } = do
889914
-- This thread is done. If there are other threads blocked in a
890915
-- ThrowTo targeted at this thread then we can wake them up now.
891-
let thread1 = thread
892-
thread' = stepThread $ thread { threadStatus = ThreadDone }
893-
wakeup = map (\(_,tid',_) -> l_labelled tid') (reverse (threadThrowTo thread))
916+
let thread1 = thread
917+
(thread', eff) = stepThread $ thread { threadStatus = ThreadDone }
918+
wakeup = map (\(_,tid',_) -> l_labelled tid') (reverse (threadThrowTo thread))
894919
(unblocked,
895920
simstate'@SimState{threads}) =
896921
unblockThreads False vClock wakeup simstate
@@ -906,7 +931,8 @@ deschedule Terminated thread@Thread { threadId = tid, threadVClock = vClock, thr
906931
[ (time, tid', (-1), tlbl', EventThrowToWakeup)
907932
| tid' <- unblocked
908933
, let tlbl' = lookupThreadLabel tid' threads ]
909-
trace
934+
$ SimPORTrace time tid (threadStep thread) tlbl (EventEffect vClock eff)
935+
trace
910936

911937
deschedule Sleep thread@Thread { threadId = tid , threadEffect = effect }
912938
simstate@SimState{runqueue, threads} =
@@ -1672,14 +1698,19 @@ currentStep Thread { threadId = stepThreadId,
16721698
threadVClock = stepVClock
16731699
} = Step {..}
16741700

1675-
stepThread :: Thread s a -> Thread s a
1701+
-- | Step a thread and return the previous `StepId` and its `Effect`.
1702+
--
1703+
stepThread :: Thread s a -> (Thread s a, Effect)
16761704
stepThread thread@Thread { threadId = tid,
16771705
threadStep = tstep,
16781706
threadVClock = vClock } =
1679-
thread { threadStep = tstep+1,
1680-
threadEffect = mempty,
1681-
threadVClock = insertVClock tid (tstep+1) vClock
1682-
}
1707+
( thread { threadStep = tstep+1,
1708+
threadEffect = mempty,
1709+
threadVClock = insertVClock tid (tstep+1) vClock
1710+
},
1711+
threadEffect thread
1712+
)
1713+
16831714

16841715
-- As we run a simulation, we collect info about each previous step
16851716
data StepInfo = StepInfo {

io-sim/src/Control/Monad/IOSimPOR/Types.hs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE NamedFieldPuns #-}
12
module Control.Monad.IOSimPOR.Types where
23

34
import qualified Data.List as List
@@ -20,7 +21,18 @@ data Effect = Effect {
2021
effectThrows :: ![ThreadId],
2122
effectWakeup :: ![ThreadId]
2223
}
23-
deriving (Eq, Show)
24+
deriving Eq
25+
26+
instance Show Effect where
27+
show Effect { effectReads, effectWrites, effectForks, effectThrows, effectWakeup } =
28+
concat $ [ "Effect { " ]
29+
++ [ "reads = " ++ show effectReads ++ ", " | not (null effectReads) ]
30+
++ [ "writes = " ++ show effectWrites ++ ", " | not (null effectWrites) ]
31+
++ [ "forks = " ++ show effectForks ++ ", " | not (null effectForks)]
32+
++ [ "throws = " ++ show effectThrows ++ ", " | not (null effectThrows) ]
33+
++ [ "wakeup = " ++ show effectWakeup ++ ", " | not (null effectWakeup) ]
34+
++ [ "}" ]
35+
2436

2537
instance Semigroup Effect where
2638
Effect r w s ts wu <> Effect r' w' s' ts' wu' =
@@ -46,7 +58,7 @@ writeEffects :: [SomeTVar s] -> Effect
4658
writeEffects rs = mempty{effectWrites = Set.fromList (map someTvarId rs)}
4759

4860
forkEffect :: ThreadId -> Effect
49-
forkEffect tid = mempty{effectForks = Set.singleton $ tid}
61+
forkEffect tid = mempty{effectForks = Set.singleton tid}
5062

5163
throwToEffect :: ThreadId -> Effect
5264
throwToEffect tid = mempty{ effectThrows = [tid] }

0 commit comments

Comments
 (0)