@@ -74,9 +74,9 @@ use rustc_middle::{mir, ty::layout::TyAndLayout};
74
74
use rustc_target:: abi:: Size ;
75
75
76
76
use crate :: {
77
- ImmTy , Immediate , InterpResult , MPlaceTy , MemPlaceMeta , MiriEvalContext , MiriEvalContextExt ,
78
- OpTy , Pointer , RangeMap , Scalar , ScalarMaybeUninit , Tag , ThreadId , VClock , VTimestamp ,
79
- VectorIdx , MemoryKind , MiriMemoryKind
77
+ ImmTy , Immediate , InterpResult , MPlaceTy , MemPlaceMeta , MemoryKind , MiriEvalContext ,
78
+ MiriEvalContextExt , MiriMemoryKind , OpTy , Pointer , RangeMap , Scalar , ScalarMaybeUninit , Tag ,
79
+ ThreadId , VClock , VTimestamp , VectorIdx ,
80
80
} ;
81
81
82
82
pub type AllocExtra = VClockAlloc ;
@@ -542,6 +542,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
542
542
Ok ( old)
543
543
}
544
544
545
+ /// Perform an conditional atomic exchange with a memory place and a new
546
+ /// scalar value, the old value is returned.
547
+ fn atomic_min_max_scalar (
548
+ & mut self ,
549
+ place : & MPlaceTy < ' tcx , Tag > ,
550
+ rhs : ImmTy < ' tcx , Tag > ,
551
+ min : bool ,
552
+ atomic : AtomicRwOp ,
553
+ ) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
554
+ let this = self . eval_context_mut ( ) ;
555
+
556
+ let old = this. allow_data_races_mut ( |this| this. read_immediate ( & place. into ( ) ) ) ?;
557
+ let lt = this. overflowing_binary_op ( mir:: BinOp :: Lt , & old, & rhs) ?. 0 . to_bool ( ) ?;
558
+
559
+ let new_val = if min {
560
+ if lt { & old } else { & rhs }
561
+ } else {
562
+ if lt { & rhs } else { & old }
563
+ } ;
564
+
565
+ this. allow_data_races_mut ( |this| this. write_immediate_to_mplace ( * * new_val, place) ) ?;
566
+
567
+ this. validate_atomic_rmw ( & place, atomic) ?;
568
+
569
+ // Return the old value.
570
+ Ok ( old)
571
+ }
572
+
545
573
/// Perform an atomic compare and exchange at a given memory location.
546
574
/// On success an atomic RMW operation is performed and on failure
547
575
/// only an atomic read occurs. If `can_fail_spuriously` is true,
@@ -687,15 +715,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
687
715
}
688
716
}
689
717
690
- fn reset_vector_clocks (
691
- & mut self ,
692
- ptr : Pointer < Tag > ,
693
- size : Size
694
- ) -> InterpResult < ' tcx > {
718
+ fn reset_vector_clocks ( & mut self , ptr : Pointer < Tag > , size : Size ) -> InterpResult < ' tcx > {
695
719
let this = self . eval_context_mut ( ) ;
696
720
if let Some ( data_race) = & mut this. memory . extra . data_race {
697
721
if data_race. multi_threaded . get ( ) {
698
- let alloc_meta = this. memory . get_raw_mut ( ptr. alloc_id ) ?. extra . data_race . as_mut ( ) . unwrap ( ) ;
722
+ let alloc_meta =
723
+ this. memory . get_raw_mut ( ptr. alloc_id ) ?. extra . data_race . as_mut ( ) . unwrap ( ) ;
699
724
alloc_meta. reset_clocks ( ptr. offset , size) ;
700
725
}
701
726
}
@@ -715,28 +740,37 @@ pub struct VClockAlloc {
715
740
716
741
impl VClockAlloc {
717
742
/// Create a new data-race detector for newly allocated memory.
718
- pub fn new_allocation ( global : & MemoryExtra , len : Size , kind : MemoryKind < MiriMemoryKind > ) -> VClockAlloc {
743
+ pub fn new_allocation (
744
+ global : & MemoryExtra ,
745
+ len : Size ,
746
+ kind : MemoryKind < MiriMemoryKind > ,
747
+ ) -> VClockAlloc {
719
748
let ( alloc_timestamp, alloc_index) = match kind {
720
749
// User allocated and stack memory should track allocation.
721
750
MemoryKind :: Machine (
722
- MiriMemoryKind :: Rust | MiriMemoryKind :: C | MiriMemoryKind :: WinHeap
723
- ) | MemoryKind :: Stack => {
751
+ MiriMemoryKind :: Rust | MiriMemoryKind :: C | MiriMemoryKind :: WinHeap ,
752
+ )
753
+ | MemoryKind :: Stack => {
724
754
let ( alloc_index, clocks) = global. current_thread_state ( ) ;
725
755
let alloc_timestamp = clocks. clock [ alloc_index] ;
726
756
( alloc_timestamp, alloc_index)
727
757
}
728
758
// Other global memory should trace races but be allocated at the 0 timestamp.
729
759
MemoryKind :: Machine (
730
- MiriMemoryKind :: Global | MiriMemoryKind :: Machine | MiriMemoryKind :: Env |
731
- MiriMemoryKind :: ExternStatic | MiriMemoryKind :: Tls
732
- ) | MemoryKind :: CallerLocation | MemoryKind :: Vtable => {
733
- ( 0 , VectorIdx :: MAX_INDEX )
734
- }
760
+ MiriMemoryKind :: Global
761
+ | MiriMemoryKind :: Machine
762
+ | MiriMemoryKind :: Env
763
+ | MiriMemoryKind :: ExternStatic
764
+ | MiriMemoryKind :: Tls ,
765
+ )
766
+ | MemoryKind :: CallerLocation
767
+ | MemoryKind :: Vtable => ( 0 , VectorIdx :: MAX_INDEX ) ,
735
768
} ;
736
769
VClockAlloc {
737
770
global : Rc :: clone ( global) ,
738
771
alloc_ranges : RefCell :: new ( RangeMap :: new (
739
- len, MemoryCellClocks :: new ( alloc_timestamp, alloc_index)
772
+ len,
773
+ MemoryCellClocks :: new ( alloc_timestamp, alloc_index) ,
740
774
) ) ,
741
775
}
742
776
}
@@ -1015,7 +1049,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
1015
1049
true ,
1016
1050
place_ptr,
1017
1051
size,
1018
- ) . map ( |_| true ) ;
1052
+ )
1053
+ . map ( |_| true ) ;
1019
1054
}
1020
1055
}
1021
1056
@@ -1267,7 +1302,6 @@ impl GlobalState {
1267
1302
. as_ref ( )
1268
1303
. expect ( "Joined with thread but thread has not terminated" ) ;
1269
1304
1270
-
1271
1305
// The join thread happens-before the current thread
1272
1306
// so update the current vector clock.
1273
1307
// Is not a release operation so the clock is not incremented.
0 commit comments