@@ -34,7 +34,7 @@ module Control.Monad.IOSim.Internal (
34
34
EventlogMarker (.. ),
35
35
ThreadId ,
36
36
ThreadLabel ,
37
- LabelledThread (.. ),
37
+ Labelled (.. ),
38
38
Trace (.. ),
39
39
TraceEvent (.. ),
40
40
liftST ,
@@ -139,7 +139,8 @@ data StmA s a where
139
139
ReturnStm :: a -> StmA s a
140
140
ThrowStm :: SomeException -> StmA s a
141
141
142
- NewTVar :: x -> (TVar s x -> StmA s b ) -> StmA s b
142
+ NewTVar :: Maybe String -> x -> (TVar s x -> StmA s b ) -> StmA s b
143
+ LabelTVar :: String -> TVar s a -> StmA s b -> StmA s b
143
144
ReadTVar :: TVar s a -> (a -> StmA s b ) -> StmA s b
144
145
WriteTVar :: TVar s a -> a -> StmA s b -> StmA s b
145
146
Retry :: StmA s b
@@ -319,7 +320,7 @@ instance MonadSTMTx (STM s) where
319
320
type TQueue_ (STM s ) = TQueueDefault (IOSim s )
320
321
type TBQueue_ (STM s ) = TBQueueDefault (IOSim s )
321
322
322
- newTVar x = STM $ \ k -> NewTVar x k
323
+ newTVar x = STM $ \ k -> NewTVar Nothing x k
323
324
readTVar tvar = STM $ \ k -> ReadTVar tvar k
324
325
writeTVar tvar x = STM $ \ k -> WriteTVar tvar x (k () )
325
326
retry = STM $ \ _ -> Retry
@@ -351,6 +352,14 @@ instance MonadSTMTx (STM s) where
351
352
isEmptyTBQueue = isEmptyTBQueueDefault
352
353
isFullTBQueue = isFullTBQueueDefault
353
354
355
+ instance MonadLabelledSTMTx (STM s ) where
356
+ labelTVar tvar label = STM $ \ k -> LabelTVar label tvar (k () )
357
+ labelTMVar = labelTMVarDefault
358
+ labelTQueue = labelTQueueDefault
359
+ labelTBQueue = labelTBQueueDefault
360
+
361
+ instance MonadLabelledSTM (IOSim s ) where
362
+
354
363
instance MonadSTM (IOSim s ) where
355
364
type STM (IOSim s ) = STM s
356
365
@@ -485,7 +494,7 @@ data Thread s a = Thread {
485
494
threadBlocked :: ! Bool ,
486
495
threadMasking :: ! MaskingState ,
487
496
-- other threads blocked in a ThrowTo to us because we are or were masked
488
- threadThrowTo :: ! [(SomeException , ThreadId )],
497
+ threadThrowTo :: ! [(SomeException , Labelled ThreadId )],
489
498
threadClockId :: ! ClockId ,
490
499
threadLabel :: Maybe ThreadLabel
491
500
}
@@ -516,22 +525,29 @@ newtype TVarId = TVarId Int deriving (Eq, Ord, Enum, Show)
516
525
newtype TimeoutId = TimeoutId Int deriving (Eq , Ord , Enum , Show )
517
526
newtype ClockId = ClockId Int deriving (Eq , Ord , Enum , Show )
518
527
528
+ unTimeoutId :: TimeoutId -> Int
529
+ unTimeoutId (TimeoutId a) = a
530
+
519
531
type ThreadLabel = String
532
+ type TVarLabel = String
520
533
521
- data LabelledThread = LabelledThread {
522
- labelledThreadId :: ThreadId ,
523
- labelledThreadLabel :: Maybe ThreadLabel
534
+ data Labelled a = Labelled {
535
+ l_labelled :: ! a ,
536
+ l_label :: ! ( Maybe String )
524
537
}
525
538
deriving (Eq , Ord , Generic )
526
- deriving Show via Quiet LabelledThread
539
+ deriving Show via Quiet ( Labelled a )
527
540
528
- labelledThreads :: Map ThreadId (Thread s a ) -> [LabelledThread ]
541
+ labelledTVarId :: TVar s a -> ST s (Labelled TVarId )
542
+ labelledTVarId TVar { tvarId, tvarLabel } = (Labelled tvarId) <$> readSTRef tvarLabel
543
+
544
+ labelledThreads :: Map ThreadId (Thread s a ) -> [Labelled ThreadId ]
529
545
labelledThreads threadMap =
530
546
-- @Map.foldr'@ (and alikes) are not strict enough, to not ratain the
531
547
-- original thread map we need to evaluate the spine of the list.
532
548
-- TODO: https://github.com/haskell/containers/issues/749
533
549
Map. foldr'
534
- (\ Thread { threadId, threadLabel } ! acc -> LabelledThread threadId threadLabel : acc)
550
+ (\ Thread { threadId, threadLabel } ! acc -> Labelled threadId threadLabel : acc)
535
551
[] threadMap
536
552
537
553
@@ -547,9 +563,9 @@ labelledThreads threadMap =
547
563
-- 'selectTraceEventsDynamic' and 'printTraceEventsSay'.
548
564
--
549
565
data Trace a = Trace ! Time ! ThreadId ! (Maybe ThreadLabel ) ! TraceEvent (Trace a )
550
- | TraceMainReturn ! Time a ! [LabelledThread ]
551
- | TraceMainException ! Time SomeException ! [LabelledThread ]
552
- | TraceDeadlock ! Time ! [LabelledThread ]
566
+ | TraceMainReturn ! Time a ! [Labelled ThreadId ]
567
+ | TraceMainException ! Time SomeException ! [Labelled ThreadId ]
568
+ | TraceDeadlock ! Time ! [Labelled ThreadId ]
553
569
deriving Show
554
570
555
571
data TraceEvent
@@ -560,17 +576,17 @@ data TraceEvent
560
576
| EventThrowTo SomeException ThreadId -- This thread used ThrowTo
561
577
| EventThrowToBlocked -- The ThrowTo blocked
562
578
| EventThrowToWakeup -- The ThrowTo resumed
563
- | EventThrowToUnmasked ThreadId -- A pending ThrowTo was activated
579
+ | EventThrowToUnmasked ( Labelled ThreadId ) -- A pending ThrowTo was activated
564
580
565
581
| EventThreadForked ThreadId
566
582
| EventThreadFinished -- terminated normally
567
583
| EventThreadUnhandled SomeException -- terminated due to unhandled exception
568
584
569
- | EventTxCommitted [TVarId ] -- tx wrote to these
570
- [TVarId ] -- and created these
585
+ | EventTxCommitted [Labelled TVarId ] -- tx wrote to these
586
+ [TVarId ] -- and created these
571
587
| EventTxAborted
572
- | EventTxBlocked [TVarId ] -- tx blocked reading these
573
- | EventTxWakeup [TVarId ] -- changed vars causing retry
588
+ | EventTxBlocked [Labelled TVarId ] -- tx blocked reading these
589
+ | EventTxWakeup [Labelled TVarId ] -- changed vars causing retry
574
590
575
591
| EventTimerCreated TimeoutId TVarId Time
576
592
| EventTimerUpdated TimeoutId Time
@@ -781,8 +797,12 @@ schedule thread@Thread{
781
797
trace)
782
798
783
799
NewTimeout d k -> do
784
- tvar <- execNewTVar nextVid TimeoutPending
785
- tvar' <- execNewTVar (succ nextVid) False
800
+ tvar <- execNewTVar nextVid
801
+ (Just $ " <<timeout-state " ++ show (unTimeoutId nextTmid) ++ " >>" )
802
+ TimeoutPending
803
+ tvar' <- execNewTVar (succ nextVid)
804
+ (Just $ " <<timeout " ++ show (unTimeoutId nextTmid) ++ " >>" )
805
+ False
786
806
let expiry = d `addTime` time
787
807
t = Timeout tvar tvar' nextTmid
788
808
timers' = PSQ. insert nextTmid expiry (TimerVars tvar tvar') timers
@@ -855,7 +875,7 @@ schedule thread@Thread{
855
875
let thread' = thread { threadControl = ThreadControl (k x) ctl }
856
876
(unblocked,
857
877
simstate') = unblockThreads wakeup simstate
858
- vids = [ tvarId tvar | SomeTVar tvar <- written ]
878
+ vids <- traverse ( \ ( SomeTVar tvar) -> labelledTVarId tvar) written
859
879
-- We don't interrupt runnable threads to provide fairness
860
880
-- anywhere else. We do it here by putting the tx that committed
861
881
-- a transaction to the back of the runqueue, behind all other
@@ -881,7 +901,7 @@ schedule thread@Thread{
881
901
882
902
StmTxBlocked read -> do
883
903
mapM_ (\ (SomeTVar tvar) -> blockThreadOnTVar tid tvar) read
884
- let vids = [ tvarId tvar | SomeTVar tvar <- read ]
904
+ vids <- traverse ( \ ( SomeTVar tvar) -> labelledTVarId tvar) read
885
905
trace <- deschedule Blocked thread simstate
886
906
return (Trace time tid tlbl (EventTxBlocked vids) trace)
887
907
@@ -930,7 +950,7 @@ schedule thread@Thread{
930
950
then do
931
951
-- The target thread has async exceptions masked so we add the
932
952
-- exception and the source thread id to the pending async exceptions.
933
- let adjustTarget t = t { threadThrowTo = (e, tid) : threadThrowTo t }
953
+ let adjustTarget t = t { threadThrowTo = (e, Labelled tid tlbl ) : threadThrowTo t }
934
954
threads' = Map. adjust adjustTarget tid' threads
935
955
trace <- deschedule Blocked thread' simstate { threads = threads' }
936
956
return $ Trace time tid tlbl (EventThrowTo e tid')
@@ -1001,7 +1021,7 @@ deschedule Interruptable thread@Thread {
1001
1021
, threadMasking = MaskedInterruptible
1002
1022
, threadThrowTo = etids }
1003
1023
(unblocked,
1004
- simstate') = unblockThreads [tid'] simstate
1024
+ simstate') = unblockThreads [l_labelled tid'] simstate
1005
1025
trace <- schedule thread' simstate'
1006
1026
return $ Trace time tid tlbl (EventThrowToUnmasked tid')
1007
1027
$ traceMany [ (time, tid'', tlbl'', EventThrowToWakeup )
@@ -1031,7 +1051,7 @@ deschedule Blocked thread simstate@SimState{threads} =
1031
1051
deschedule Terminated thread simstate@ SimState { curTime = time, threads } = do
1032
1052
-- This thread is done. If there are other threads blocked in a
1033
1053
-- ThrowTo targeted at this thread then we can wake them up now.
1034
- let wakeup = map snd (reverse (threadThrowTo thread))
1054
+ let wakeup = map (l_labelled . snd ) (reverse (threadThrowTo thread))
1035
1055
(unblocked,
1036
1056
simstate') = unblockThreads wakeup simstate
1037
1057
trace <- reschedule simstate'
@@ -1200,6 +1220,9 @@ data TVar s a = TVar {
1200
1220
--
1201
1221
tvarId :: ! TVarId ,
1202
1222
1223
+ -- | Label.
1224
+ tvarLabel :: ! (STRef s (Maybe TVarLabel )),
1225
+
1203
1226
-- | The var's current value
1204
1227
--
1205
1228
tvarCurrent :: ! (STRef s a ),
@@ -1345,10 +1368,14 @@ execAtomically =
1345
1368
let ctl' = OrElseLeftFrame b k written writtenSeq ctl
1346
1369
go ctl' read Map. empty [] nextVid a
1347
1370
1348
- NewTVar x k -> do
1349
- v <- execNewTVar nextVid x
1371
+ NewTVar ! mbLabel x k -> do
1372
+ v <- execNewTVar nextVid mbLabel x
1350
1373
go ctl read written writtenSeq (succ nextVid) (k v)
1351
1374
1375
+ LabelTVar ! label tvar k -> do
1376
+ writeSTRef (tvarLabel tvar) $! (Just label)
1377
+ go ctl read written writtenSeq nextVid k
1378
+
1352
1379
ReadTVar v k
1353
1380
| tvarId v `Map.member` read -> do
1354
1381
x <- execReadTVar v
@@ -1400,12 +1427,14 @@ execAtomically' = go Map.empty
1400
1427
_ -> error " execAtomically': only for special case of reads and writes"
1401
1428
1402
1429
1403
- execNewTVar :: TVarId -> a -> ST s (TVar s a )
1404
- execNewTVar nextVid x = do
1430
+ execNewTVar :: TVarId -> Maybe String -> a -> ST s (TVar s a )
1431
+ execNewTVar nextVid ! mbLabel x = do
1432
+ tvarLabel <- newSTRef mbLabel
1405
1433
tvarCurrent <- newSTRef x
1406
1434
tvarUndo <- newSTRef []
1407
1435
tvarBlocked <- newSTRef ([] , Set. empty)
1408
- return TVar {tvarId = nextVid, tvarCurrent, tvarUndo, tvarBlocked}
1436
+ return TVar {tvarId = nextVid, tvarLabel,
1437
+ tvarCurrent, tvarUndo, tvarBlocked}
1409
1438
1410
1439
execReadTVar :: TVar s a -> ST s a
1411
1440
execReadTVar TVar {tvarCurrent} = readSTRef tvarCurrent
@@ -1463,10 +1492,10 @@ unblockAllThreadsFromTVar TVar{tvarBlocked} = do
1463
1492
-- the var writes that woke them.
1464
1493
--
1465
1494
threadsUnblockedByWrites :: [SomeTVar s ]
1466
- -> ST s ([ThreadId ], Map ThreadId (Set TVarId ))
1495
+ -> ST s ([ThreadId ], Map ThreadId (Set ( Labelled TVarId ) ))
1467
1496
threadsUnblockedByWrites written = do
1468
1497
tidss <- sequence
1469
- [ (,) (tvarId tvar) <$ > readTVarBlockedThreads tvar
1498
+ [ (,) <$> labelledTVarId tvar <* > readTVarBlockedThreads tvar
1470
1499
| SomeTVar tvar <- written ]
1471
1500
-- Threads to wake up, in wake up order, annotated with the vars written that
1472
1501
-- caused the unblocking.
0 commit comments