@@ -88,18 +88,33 @@ impl From<ThreadId> for u64 {
8888 }
8989}
9090
91+ /// Keeps track of what the thread is blocked on.
92+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
93+ pub enum BlockReason {
94+ /// The thread tried to join the specified thread and is blocked until that
95+ /// thread terminates.
96+ Join ( ThreadId ) ,
97+ /// Waiting for time to pass.
98+ Sleep ,
99+ /// Blocked on a mutex.
100+ Mutex ( MutexId ) ,
101+ /// Blocked on a condition variable.
102+ Condvar ( CondvarId ) ,
103+ /// Blocked on a reader-writer lock.
104+ RwLock ( RwLockId ) ,
105+ /// Blocled on a Futex variable.
106+ Futex { addr : u64 } ,
107+ /// Blocked on an InitOnce.
108+ InitOnce ( InitOnceId ) ,
109+ }
110+
91111/// The state of a thread.
92112#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
93113pub enum ThreadState {
94114 /// The thread is enabled and can be executed.
95115 Enabled ,
96- /// The thread tried to join the specified thread and is blocked until that
97- /// thread terminates.
98- BlockedOnJoin ( ThreadId ) ,
99- /// The thread is blocked on some synchronization primitive. It is the
100- /// responsibility of the synchronization primitives to track threads that
101- /// are blocked by them.
102- BlockedOnSync ,
116+ /// The thread is blocked on something.
117+ Blocked ( BlockReason ) ,
103118 /// The thread has terminated its execution. We do not delete terminated
104119 /// threads (FIXME: why?).
105120 Terminated ,
@@ -296,17 +311,17 @@ impl VisitProvenance for Frame<'_, '_, Provenance, FrameExtra<'_>> {
296311
297312/// A specific moment in time.
298313#[ derive( Debug ) ]
299- pub enum Time {
314+ pub enum CallbackTime {
300315 Monotonic ( Instant ) ,
301316 RealTime ( SystemTime ) ,
302317}
303318
304- impl Time {
319+ impl CallbackTime {
305320 /// How long do we have to wait from now until the specified time?
306321 fn get_wait_time ( & self , clock : & Clock ) -> Duration {
307322 match self {
308- Time :: Monotonic ( instant) => instant. duration_since ( clock. now ( ) ) ,
309- Time :: RealTime ( time) =>
323+ CallbackTime :: Monotonic ( instant) => instant. duration_since ( clock. now ( ) ) ,
324+ CallbackTime :: RealTime ( time) =>
310325 time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: new ( 0 , 0 ) ) ,
311326 }
312327 }
@@ -318,7 +333,7 @@ impl Time {
318333/// conditional variable, the signal handler deletes the callback.
319334struct TimeoutCallbackInfo < ' mir , ' tcx > {
320335 /// The callback should be called no earlier than this time.
321- call_time : Time ,
336+ call_time : CallbackTime ,
322337 /// The called function.
323338 callback : TimeoutCallback < ' mir , ' tcx > ,
324339}
@@ -539,7 +554,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
539554 self . threads [ joined_thread_id] . join_status = ThreadJoinStatus :: Joined ;
540555 if self . threads [ joined_thread_id] . state != ThreadState :: Terminated {
541556 // The joined thread is still running, we need to wait for it.
542- self . active_thread_mut ( ) . state = ThreadState :: BlockedOnJoin ( joined_thread_id) ;
557+ self . active_thread_mut ( ) . state =
558+ ThreadState :: Blocked ( BlockReason :: Join ( joined_thread_id) ) ;
543559 trace ! (
544560 "{:?} blocked on {:?} when trying to join" ,
545561 self . active_thread,
@@ -569,10 +585,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
569585 throw_ub_format ! ( "trying to join itself" ) ;
570586 }
571587
588+ // Sanity check `join_status`.
572589 assert ! (
573- self . threads
574- . iter ( )
575- . all ( |thread| thread . state != ThreadState :: BlockedOnJoin ( joined_thread_id ) ) ,
590+ self . threads. iter ( ) . all ( |thread| {
591+ thread . state != ThreadState :: Blocked ( BlockReason :: Join ( joined_thread_id ) )
592+ } ) ,
576593 "this thread already has threads waiting for its termination"
577594 ) ;
578595
@@ -594,16 +611,17 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
594611 }
595612
596613 /// Put the thread into the blocked state.
597- fn block_thread ( & mut self , thread : ThreadId ) {
614+ fn block_thread ( & mut self , thread : ThreadId , reason : BlockReason ) {
598615 let state = & mut self . threads [ thread] . state ;
599616 assert_eq ! ( * state, ThreadState :: Enabled ) ;
600- * state = ThreadState :: BlockedOnSync ;
617+ * state = ThreadState :: Blocked ( reason ) ;
601618 }
602619
603620 /// Put the blocked thread into the enabled state.
604- fn unblock_thread ( & mut self , thread : ThreadId ) {
621+ /// Sanity-checks that the thread previously was blocked for the right reason.
622+ fn unblock_thread ( & mut self , thread : ThreadId , reason : BlockReason ) {
605623 let state = & mut self . threads [ thread] . state ;
606- assert_eq ! ( * state, ThreadState :: BlockedOnSync ) ;
624+ assert_eq ! ( * state, ThreadState :: Blocked ( reason ) ) ;
607625 * state = ThreadState :: Enabled ;
608626 }
609627
@@ -622,7 +640,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
622640 fn register_timeout_callback (
623641 & mut self ,
624642 thread : ThreadId ,
625- call_time : Time ,
643+ call_time : CallbackTime ,
626644 callback : TimeoutCallback < ' mir , ' tcx > ,
627645 ) {
628646 self . timeout_callbacks
@@ -683,7 +701,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
683701 // Check if we need to unblock any threads.
684702 let mut joined_threads = vec ! [ ] ; // store which threads joined, we'll need it
685703 for ( i, thread) in self . threads . iter_enumerated_mut ( ) {
686- if thread. state == ThreadState :: BlockedOnJoin ( self . active_thread ) {
704+ if thread. state == ThreadState :: Blocked ( BlockReason :: Join ( self . active_thread ) ) {
687705 // The thread has terminated, mark happens-before edge to joining thread
688706 if data_race. is_some ( ) {
689707 joined_threads. push ( i) ;
@@ -999,13 +1017,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
9991017 }
10001018
10011019 #[ inline]
1002- fn block_thread ( & mut self , thread : ThreadId ) {
1003- self . eval_context_mut ( ) . machine . threads . block_thread ( thread) ;
1020+ fn block_thread ( & mut self , thread : ThreadId , reason : BlockReason ) {
1021+ self . eval_context_mut ( ) . machine . threads . block_thread ( thread, reason ) ;
10041022 }
10051023
10061024 #[ inline]
1007- fn unblock_thread ( & mut self , thread : ThreadId ) {
1008- self . eval_context_mut ( ) . machine . threads . unblock_thread ( thread) ;
1025+ fn unblock_thread ( & mut self , thread : ThreadId , reason : BlockReason ) {
1026+ self . eval_context_mut ( ) . machine . threads . unblock_thread ( thread, reason ) ;
10091027 }
10101028
10111029 #[ inline]
@@ -1027,11 +1045,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10271045 fn register_timeout_callback (
10281046 & mut self ,
10291047 thread : ThreadId ,
1030- call_time : Time ,
1048+ call_time : CallbackTime ,
10311049 callback : TimeoutCallback < ' mir , ' tcx > ,
10321050 ) {
10331051 let this = self . eval_context_mut ( ) ;
1034- if !this. machine . communicate ( ) && matches ! ( call_time, Time :: RealTime ( ..) ) {
1052+ if !this. machine . communicate ( ) && matches ! ( call_time, CallbackTime :: RealTime ( ..) ) {
10351053 panic ! ( "cannot have `RealTime` callback with isolation enabled!" )
10361054 }
10371055 this. machine . threads . register_timeout_callback ( thread, call_time, callback) ;
0 commit comments