@@ -35,6 +35,10 @@ macro_rules! declare_id {
35
35
}
36
36
}
37
37
38
+ impl $crate:: VisitProvenance for $name {
39
+ fn visit_provenance( & self , _visit: & mut VisitWith <' _>) { }
40
+ }
41
+
38
42
impl Idx for $name {
39
43
fn new( idx: usize ) -> Self {
40
44
// We use 0 as a sentinel value (see the comment above) and,
@@ -258,6 +262,25 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
258
262
Ok ( new_index)
259
263
}
260
264
}
265
+
266
+ fn condvar_reacquire_mutex (
267
+ & mut self ,
268
+ mutex : MutexId ,
269
+ retval : Scalar < Provenance > ,
270
+ dest : MPlaceTy < ' tcx , Provenance > ,
271
+ ) -> InterpResult < ' tcx > {
272
+ let this = self . eval_context_mut ( ) ;
273
+ if this. mutex_is_locked ( mutex) {
274
+ assert_ne ! ( this. mutex_get_owner( mutex) , this. active_thread( ) ) ;
275
+ this. mutex_enqueue_and_block ( mutex, retval, dest) ;
276
+ } else {
277
+ // We can have it right now!
278
+ this. mutex_lock ( mutex) ;
279
+ // Don't forget to write the return value.
280
+ this. write_scalar ( retval, & dest) ?;
281
+ }
282
+ Ok ( ( ) )
283
+ }
261
284
}
262
285
263
286
// Public interface to synchronization primitives. Please note that in most
@@ -384,29 +407,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
384
407
assert ! ( this. mutex_is_locked( id) , "queing on unlocked mutex" ) ;
385
408
let thread = this. active_thread ( ) ;
386
409
this. machine . sync . mutexes [ id] . queue . push_back ( thread) ;
387
- this. block_thread ( BlockReason :: Mutex ( id) , None , Callback { id, retval, dest } ) ;
388
-
389
- struct Callback < ' tcx > {
390
- id : MutexId ,
391
- retval : Scalar < Provenance > ,
392
- dest : MPlaceTy < ' tcx , Provenance > ,
393
- }
394
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
395
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
396
- let Callback { id : _, retval, dest } = self ;
397
- retval. visit_provenance ( visit) ;
398
- dest. visit_provenance ( visit) ;
399
- }
400
- }
401
- impl < ' mir , ' tcx : ' mir > UnblockCallback < ' mir , ' tcx > for Callback < ' tcx > {
402
- fn unblock ( self : Box < Self > , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
403
- assert ! ( !this. mutex_is_locked( self . id) ) ;
404
- this. mutex_lock ( self . id ) ;
405
-
406
- this. write_scalar ( self . retval , & self . dest ) ?;
407
- Ok ( ( ) )
408
- }
409
- }
410
+ this. block_thread (
411
+ BlockReason :: Mutex ( id) ,
412
+ None ,
413
+ callback ! (
414
+ @capture<' tcx> {
415
+ id: MutexId ,
416
+ retval: Scalar <Provenance >,
417
+ dest: MPlaceTy <' tcx, Provenance >,
418
+ }
419
+ @unblock = |this| {
420
+ assert!( !this. mutex_is_locked( id) ) ;
421
+ this. mutex_lock( id) ;
422
+ this. write_scalar( retval, & dest) ?;
423
+ Ok ( ( ) )
424
+ }
425
+ ) ,
426
+ ) ;
410
427
}
411
428
412
429
#[ inline]
@@ -500,27 +517,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
500
517
let thread = this. active_thread ( ) ;
501
518
assert ! ( this. rwlock_is_write_locked( id) , "read-queueing on not write locked rwlock" ) ;
502
519
this. machine . sync . rwlocks [ id] . reader_queue . push_back ( thread) ;
503
- this. block_thread ( BlockReason :: RwLock ( id) , None , Callback { id, retval, dest } ) ;
504
-
505
- struct Callback < ' tcx > {
506
- id : RwLockId ,
507
- retval : Scalar < Provenance > ,
508
- dest : MPlaceTy < ' tcx , Provenance > ,
509
- }
510
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
511
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
512
- let Callback { id : _, retval, dest } = self ;
513
- retval. visit_provenance ( visit) ;
514
- dest. visit_provenance ( visit) ;
515
- }
516
- }
517
- impl < ' mir , ' tcx : ' mir > UnblockCallback < ' mir , ' tcx > for Callback < ' tcx > {
518
- fn unblock ( self : Box < Self > , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
519
- this. rwlock_reader_lock ( self . id ) ;
520
- this. write_scalar ( self . retval , & self . dest ) ?;
521
- Ok ( ( ) )
522
- }
523
- }
520
+ this. block_thread (
521
+ BlockReason :: RwLock ( id) ,
522
+ None ,
523
+ callback ! (
524
+ @capture<' tcx> {
525
+ id: RwLockId ,
526
+ retval: Scalar <Provenance >,
527
+ dest: MPlaceTy <' tcx, Provenance >,
528
+ }
529
+ @unblock = |this| {
530
+ this. rwlock_reader_lock( id) ;
531
+ this. write_scalar( retval, & dest) ?;
532
+ Ok ( ( ) )
533
+ }
534
+ ) ,
535
+ ) ;
524
536
}
525
537
526
538
/// Lock by setting the writer that owns the lock.
@@ -588,27 +600,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
588
600
assert ! ( this. rwlock_is_locked( id) , "write-queueing on unlocked rwlock" ) ;
589
601
let thread = this. active_thread ( ) ;
590
602
this. machine . sync . rwlocks [ id] . writer_queue . push_back ( thread) ;
591
- this. block_thread ( BlockReason :: RwLock ( id) , None , Callback { id, retval, dest } ) ;
592
-
593
- struct Callback < ' tcx > {
594
- id : RwLockId ,
595
- retval : Scalar < Provenance > ,
596
- dest : MPlaceTy < ' tcx , Provenance > ,
597
- }
598
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
599
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
600
- let Callback { id : _, retval, dest } = self ;
601
- retval. visit_provenance ( visit) ;
602
- dest. visit_provenance ( visit) ;
603
- }
604
- }
605
- impl < ' mir , ' tcx : ' mir > UnblockCallback < ' mir , ' tcx > for Callback < ' tcx > {
606
- fn unblock ( self : Box < Self > , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
607
- this. rwlock_writer_lock ( self . id ) ;
608
- this. write_scalar ( self . retval , & self . dest ) ?;
609
- Ok ( ( ) )
610
- }
611
- }
603
+ this. block_thread (
604
+ BlockReason :: RwLock ( id) ,
605
+ None ,
606
+ callback ! (
607
+ @capture<' tcx> {
608
+ id: RwLockId ,
609
+ retval: Scalar <Provenance >,
610
+ dest: MPlaceTy <' tcx, Provenance >,
611
+ }
612
+ @unblock = |this| {
613
+ this. rwlock_writer_lock( id) ;
614
+ this. write_scalar( retval, & dest) ?;
615
+ Ok ( ( ) )
616
+ }
617
+ ) ,
618
+ ) ;
612
619
}
613
620
614
621
/// Is the conditional variable awaited?
@@ -648,71 +655,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
648
655
this. block_thread (
649
656
BlockReason :: Condvar ( condvar) ,
650
657
timeout,
651
- Callback { condvar, mutex, retval_succ, retval_timeout, dest } ,
652
- ) ;
653
- return Ok ( ( ) ) ;
654
-
655
- struct Callback < ' tcx > {
656
- condvar : CondvarId ,
657
- mutex : MutexId ,
658
- retval_succ : Scalar < Provenance > ,
659
- retval_timeout : Scalar < Provenance > ,
660
- dest : MPlaceTy < ' tcx , Provenance > ,
661
- }
662
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
663
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
664
- let Callback { condvar : _, mutex : _, retval_succ, retval_timeout, dest } = self ;
665
- retval_succ. visit_provenance ( visit) ;
666
- retval_timeout. visit_provenance ( visit) ;
667
- dest. visit_provenance ( visit) ;
668
- }
669
- }
670
- impl < ' tcx , ' mir > Callback < ' tcx > {
671
- #[ allow( clippy:: boxed_local) ]
672
- fn reacquire_mutex (
673
- self : Box < Self > ,
674
- this : & mut MiriInterpCx < ' mir , ' tcx > ,
675
- retval : Scalar < Provenance > ,
676
- ) -> InterpResult < ' tcx > {
677
- if this. mutex_is_locked ( self . mutex ) {
678
- assert_ne ! ( this. mutex_get_owner( self . mutex) , this. active_thread( ) ) ;
679
- this. mutex_enqueue_and_block ( self . mutex , retval, self . dest ) ;
680
- } else {
681
- // We can have it right now!
682
- this. mutex_lock ( self . mutex ) ;
683
- // Don't forget to write the return value.
684
- this. write_scalar ( retval, & self . dest ) ?;
658
+ callback ! (
659
+ @capture<' tcx> {
660
+ condvar: CondvarId ,
661
+ mutex: MutexId ,
662
+ retval_succ: Scalar <Provenance >,
663
+ retval_timeout: Scalar <Provenance >,
664
+ dest: MPlaceTy <' tcx, Provenance >,
685
665
}
686
- Ok ( ( ) )
687
- }
688
- }
689
- impl < ' mir , ' tcx : ' mir > UnblockCallback < ' mir , ' tcx > for Callback < ' tcx > {
690
- fn unblock ( self : Box < Self > , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
691
- // The condvar was signaled. Make sure we get the clock for that.
692
- if let Some ( data_race ) = & this . machine . data_race {
693
- data_race . acquire_clock (
694
- & this . machine . sync . condvars [ self . condvar ] . clock ,
695
- & this . machine . threads ,
696
- ) ;
666
+ @unblock = |this| {
667
+ // The condvar was signaled. Make sure we get the clock for that.
668
+ if let Some ( data_race ) = & this . machine . data_race {
669
+ data_race . acquire_clock (
670
+ & this . machine . sync . condvars [ condvar ] . clock ,
671
+ & this . machine . threads ,
672
+ ) ;
673
+ }
674
+ // Try to acquire the mutex.
675
+ // The timeout only applies to the first wait (until the signal), not for mutex acquisition.
676
+ this . condvar_reacquire_mutex ( mutex , retval_succ , dest )
697
677
}
698
- // Try to acquire the mutex.
699
- // The timeout only applies to the first wait (until the signal), not for mutex acquisition.
700
- let retval = self . retval_succ ;
701
- self . reacquire_mutex ( this, retval)
702
- }
703
- fn timeout (
704
- self : Box < Self > ,
705
- this : & mut InterpCx < ' mir , ' tcx , MiriMachine < ' mir , ' tcx > > ,
706
- ) -> InterpResult < ' tcx > {
707
- // We have to remove the waiter from the queue again.
708
- let thread = this. active_thread ( ) ;
709
- let waiters = & mut this. machine . sync . condvars [ self . condvar ] . waiters ;
710
- waiters. retain ( |waiter| * waiter != thread) ;
711
- // Now get back the lock.
712
- let retval = self . retval_timeout ;
713
- self . reacquire_mutex ( this, retval)
714
- }
715
- }
678
+ @timeout = |this| {
679
+ // We have to remove the waiter from the queue again.
680
+ let thread = this. active_thread( ) ;
681
+ let waiters = & mut this. machine. sync. condvars[ condvar] . waiters;
682
+ waiters. retain( |waiter| * waiter != thread) ;
683
+ // Now get back the lock.
684
+ this. condvar_reacquire_mutex( mutex, retval_timeout, dest)
685
+ }
686
+ ) ,
687
+ ) ;
688
+ return Ok ( ( ) ) ;
716
689
}
717
690
718
691
/// Wake up some thread (if there is any) sleeping on the conditional
@@ -755,50 +728,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
755
728
this. block_thread (
756
729
BlockReason :: Futex { addr } ,
757
730
timeout,
758
- Callback { addr, retval_succ, retval_timeout, dest, errno_timeout } ,
759
- ) ;
760
-
761
- struct Callback < ' tcx > {
762
- addr : u64 ,
763
- retval_succ : Scalar < Provenance > ,
764
- retval_timeout : Scalar < Provenance > ,
765
- dest : MPlaceTy < ' tcx , Provenance > ,
766
- errno_timeout : Scalar < Provenance > ,
767
- }
768
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
769
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
770
- let Callback { addr : _, retval_succ, retval_timeout, dest, errno_timeout } = self ;
771
- retval_succ. visit_provenance ( visit) ;
772
- retval_timeout. visit_provenance ( visit) ;
773
- dest. visit_provenance ( visit) ;
774
- errno_timeout. visit_provenance ( visit) ;
775
- }
776
- }
777
- impl < ' mir , ' tcx : ' mir > UnblockCallback < ' mir , ' tcx > for Callback < ' tcx > {
778
- fn unblock ( self : Box < Self > , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
779
- let futex = this. machine . sync . futexes . get ( & self . addr ) . unwrap ( ) ;
780
- // Acquire the clock of the futex.
781
- if let Some ( data_race) = & this. machine . data_race {
782
- data_race. acquire_clock ( & futex. clock , & this. machine . threads ) ;
731
+ callback ! (
732
+ @capture<' tcx> {
733
+ addr: u64 ,
734
+ retval_succ: Scalar <Provenance >,
735
+ retval_timeout: Scalar <Provenance >,
736
+ dest: MPlaceTy <' tcx, Provenance >,
737
+ errno_timeout: Scalar <Provenance >,
783
738
}
784
- // Write the return value.
785
- this. write_scalar ( self . retval_succ , & self . dest ) ?;
786
- Ok ( ( ) )
787
- }
788
- fn timeout (
789
- self : Box < Self > ,
790
- this : & mut InterpCx < ' mir , ' tcx , MiriMachine < ' mir , ' tcx > > ,
791
- ) -> InterpResult < ' tcx > {
792
- // Remove the waiter from the futex.
793
- let thread = this. active_thread ( ) ;
794
- let futex = this. machine . sync . futexes . get_mut ( & self . addr ) . unwrap ( ) ;
795
- futex. waiters . retain ( |waiter| waiter. thread != thread) ;
796
- // Set errno and write return value.
797
- this. set_last_error ( self . errno_timeout ) ?;
798
- this. write_scalar ( self . retval_timeout , & self . dest ) ?;
799
- Ok ( ( ) )
800
- }
801
- }
739
+ @unblock = |this| {
740
+ let futex = this. machine. sync. futexes. get( & addr) . unwrap( ) ;
741
+ // Acquire the clock of the futex.
742
+ if let Some ( data_race) = & this. machine. data_race {
743
+ data_race. acquire_clock( & futex. clock, & this. machine. threads) ;
744
+ }
745
+ // Write the return value.
746
+ this. write_scalar( retval_succ, & dest) ?;
747
+ Ok ( ( ) )
748
+ }
749
+ @timeout = |this| {
750
+ // Remove the waiter from the futex.
751
+ let thread = this. active_thread( ) ;
752
+ let futex = this. machine. sync. futexes. get_mut( & addr) . unwrap( ) ;
753
+ futex. waiters. retain( |waiter| waiter. thread != thread) ;
754
+ // Set errno and write return value.
755
+ this. set_last_error( errno_timeout) ?;
756
+ this. write_scalar( retval_timeout, & dest) ?;
757
+ Ok ( ( ) )
758
+ }
759
+ ) ,
760
+ ) ;
802
761
}
803
762
804
763
/// Returns whether anything was woken.
0 commit comments