@@ -74,9 +74,9 @@ use rustc_middle::{mir, ty::layout::TyAndLayout};
7474use rustc_target:: abi:: Size ;
7575
7676use 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 ,
8080} ;
8181
8282pub type AllocExtra = VClockAlloc ;
@@ -263,7 +263,7 @@ impl MemoryCellClocks {
263263 atomic_ops : None ,
264264 }
265265 }
266-
266+
267267 /// Load the internal atomic memory cells if they exist.
268268 #[ inline]
269269 fn atomic ( & self ) -> Option < & AtomicMemoryCellClocks > {
@@ -323,7 +323,7 @@ impl MemoryCellClocks {
323323 /// store relaxed semantics.
324324 fn store_relaxed ( & mut self , clocks : & ThreadClockSet , index : VectorIdx ) -> Result < ( ) , DataRace > {
325325 self . atomic_write_detect ( clocks, index) ?;
326-
326+
327327 // The handling of release sequences was changed in C++20 and so
328328 // the code here is different to the paper since now all relaxed
329329 // stores block release sequences. The exception for same-thread
@@ -542,6 +542,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
542542 Ok ( old)
543543 }
544544
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+
545573 /// Perform an atomic compare and exchange at a given memory location.
546574 /// On success an atomic RMW operation is performed and on failure
547575 /// only an atomic read occurs. If `can_fail_spuriously` is true,
@@ -678,7 +706,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
678706 // Either Release | AcqRel | SeqCst
679707 clocks. apply_release_fence ( ) ;
680708 }
681-
709+
682710 // Increment timestamp in case of release semantics.
683711 Ok ( atomic != AtomicFenceOp :: Acquire )
684712 } )
@@ -687,15 +715,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
687715 }
688716 }
689717
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 > {
695719 let this = self . eval_context_mut ( ) ;
696720 if let Some ( data_race) = & mut this. memory . extra . data_race {
697721 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 ( ) ;
699724 alloc_meta. reset_clocks ( ptr. offset , size) ;
700725 }
701726 }
@@ -715,28 +740,37 @@ pub struct VClockAlloc {
715740
716741impl VClockAlloc {
717742 /// 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 {
719748 let ( alloc_timestamp, alloc_index) = match kind {
720749 // User allocated and stack memory should track allocation.
721750 MemoryKind :: Machine (
722- MiriMemoryKind :: Rust | MiriMemoryKind :: C | MiriMemoryKind :: WinHeap
723- ) | MemoryKind :: Stack => {
751+ MiriMemoryKind :: Rust | MiriMemoryKind :: C | MiriMemoryKind :: WinHeap ,
752+ )
753+ | MemoryKind :: Stack => {
724754 let ( alloc_index, clocks) = global. current_thread_state ( ) ;
725755 let alloc_timestamp = clocks. clock [ alloc_index] ;
726756 ( alloc_timestamp, alloc_index)
727757 }
728758 // Other global memory should trace races but be allocated at the 0 timestamp.
729759 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 ) ,
735768 } ;
736769 VClockAlloc {
737770 global : Rc :: clone ( global) ,
738771 alloc_ranges : RefCell :: new ( RangeMap :: new (
739- len, MemoryCellClocks :: new ( alloc_timestamp, alloc_index)
772+ len,
773+ MemoryCellClocks :: new ( alloc_timestamp, alloc_index) ,
740774 ) ) ,
741775 }
742776 }
@@ -1015,7 +1049,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
10151049 true ,
10161050 place_ptr,
10171051 size,
1018- ) . map ( |_| true ) ;
1052+ )
1053+ . map ( |_| true ) ;
10191054 }
10201055 }
10211056
@@ -1267,7 +1302,6 @@ impl GlobalState {
12671302 . as_ref ( )
12681303 . expect ( "Joined with thread but thread has not terminated" ) ;
12691304
1270-
12711305 // The join thread happens-before the current thread
12721306 // so update the current vector clock.
12731307 // Is not a release operation so the clock is not incremented.
0 commit comments