@@ -19,7 +19,7 @@ use crate::concurrency::data_race;
1919use crate :: shims:: tls;
2020use crate :: * ;
2121
22- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
22+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
2323enum SchedulingAction {
2424 /// Execute step on the active thread.
2525 ExecuteStep ,
@@ -30,6 +30,7 @@ enum SchedulingAction {
3030}
3131
3232/// What to do with TLS allocations from terminated threads
33+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
3334pub enum TlsAllocAction {
3435 /// Deallocate backing memory of thread-local statics as usual
3536 Deallocate ,
@@ -38,71 +39,18 @@ pub enum TlsAllocAction {
3839 Leak ,
3940}
4041
41- /// Trait for callbacks that are executed when a thread gets unblocked.
42- pub trait UnblockCallback < ' tcx > : VisitProvenance {
43- /// Will be invoked when the thread was unblocked the "regular" way,
44- /// i.e. whatever event it was blocking on has happened.
45- fn unblock ( self : Box < Self > , ecx : & mut InterpCx < ' tcx , MiriMachine < ' tcx > > ) -> InterpResult < ' tcx > ;
46-
47- /// Will be invoked when the timeout ellapsed without the event the
48- /// thread was blocking on having occurred.
49- fn timeout ( self : Box < Self > , _ecx : & mut InterpCx < ' tcx , MiriMachine < ' tcx > > )
50- -> InterpResult < ' tcx > ;
42+ /// The argument type for the "unblock" callback, indicating why the thread got unblocked.
43+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
44+ pub enum UnblockKind {
45+ /// Operation completed successfully, thread continues normal execution.
46+ Ready ,
47+ /// The operation did not complete within its specified duration.
48+ TimedOut ,
5149}
52- pub type DynUnblockCallback < ' tcx > = Box < dyn UnblockCallback < ' tcx > + ' tcx > ;
53-
54- #[ macro_export]
55- macro_rules! callback {
56- (
57- @capture<$tcx: lifetime $( , ) ? $( $lft: lifetime) ,* > { $( $name: ident: $type: ty) ,* $( , ) ? }
58- @unblock = |$this: ident| $unblock: block
59- ) => {
60- callback!(
61- @capture<$tcx, $( $lft) ,* > { $( $name: $type) ,* }
62- @unblock = |$this| $unblock
63- @timeout = |_this| {
64- unreachable!(
65- "timeout on a thread that was blocked without a timeout (or someone forgot to overwrite this method)"
66- )
67- }
68- )
69- } ;
70- (
71- @capture<$tcx: lifetime $( , ) ? $( $lft: lifetime) ,* > { $( $name: ident: $type: ty) ,* $( , ) ? }
72- @unblock = |$this: ident| $unblock: block
73- @timeout = |$this_timeout: ident| $timeout: block
74- ) => { {
75- struct Callback <$tcx, $( $lft) ,* > {
76- $( $name: $type, ) *
77- _phantom: std:: marker:: PhantomData <& $tcx ( ) >,
78- }
79-
80- impl <$tcx, $( $lft) ,* > VisitProvenance for Callback <$tcx, $( $lft) ,* > {
81- #[ allow( unused_variables) ]
82- fn visit_provenance( & self , visit: & mut VisitWith <' _>) {
83- $(
84- self . $name. visit_provenance( visit) ;
85- ) *
86- }
87- }
88-
89- impl <$tcx, $( $lft) ,* > UnblockCallback <$tcx> for Callback <$tcx, $( $lft) ,* > {
90- fn unblock( self : Box <Self >, $this: & mut MiriInterpCx <$tcx>) -> InterpResult <$tcx> {
91- #[ allow( unused_variables) ]
92- let Callback { $( $name, ) * _phantom } = * self ;
93- $unblock
94- }
9550
96- fn timeout( self : Box <Self >, $this_timeout: & mut MiriInterpCx <$tcx>) -> InterpResult <$tcx> {
97- #[ allow( unused_variables) ]
98- let Callback { $( $name, ) * _phantom } = * self ;
99- $timeout
100- }
101- }
102-
103- Box :: new( Callback { $( $name, ) * _phantom: std:: marker:: PhantomData } )
104- } }
105- }
51+ /// Type alias for unblock callbacks, i.e. machine callbacks invoked when
52+ /// a thread gets unblocked.
53+ pub type DynUnblockCallback < ' tcx > = DynMachineCallback < ' tcx , UnblockKind > ;
10654
10755/// A thread identifier.
10856#[ derive( Clone , Copy , Debug , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
@@ -656,7 +604,8 @@ impl<'tcx> ThreadManager<'tcx> {
656604 @capture<' tcx> {
657605 joined_thread_id: ThreadId ,
658606 }
659- @unblock = |this| {
607+ |this, unblock: UnblockKind | {
608+ assert_eq!( unblock, UnblockKind :: Ready ) ;
660609 if let Some ( data_race) = & mut this. machine. data_race {
661610 data_race. thread_joined( & this. machine. threads, joined_thread_id) ;
662611 }
@@ -842,7 +791,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
842791 // 2. Make the scheduler the only place that can change the active
843792 // thread.
844793 let old_thread = this. machine . threads . set_active_thread_id ( thread) ;
845- callback. timeout ( this) ?;
794+ callback. call ( this, UnblockKind :: TimedOut ) ?;
846795 this. machine . threads . set_active_thread_id ( old_thread) ;
847796 }
848797 // found_callback can remain None if the computer's clock
@@ -1084,7 +1033,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10841033 } ;
10851034 // The callback must be executed in the previously blocked thread.
10861035 let old_thread = this. machine . threads . set_active_thread_id ( thread) ;
1087- callback. unblock ( this) ?;
1036+ callback. call ( this, UnblockKind :: Ready ) ?;
10881037 this. machine . threads . set_active_thread_id ( old_thread) ;
10891038 interp_ok ( ( ) )
10901039 }
0 commit comments