3737//! to a acquire load and a release store given the global sequentially consistent order
3838//! of the schedule.
3939//!
40+ //! The timestamps used in the data-race detector assign each sequence of non-atomic operations
41+ //! followed by a single atomic or concurrent operation a single timestamp.
42+ //! Write, Read, Write, ThreadJoin will be represented by a single timestamp value on a thread
43+ //! This is because extra increment operations between the operations in the sequence are not
44+ //! required for accurate reporting of data-race values.
45+ //!
46+ //! If the timestamp was not incremented after the atomic operation, then data-races would not be detected:
47+ //! Example - this should report a data-race but does not:
48+ //! t1: (x,0), atomic[release A], t1=(x+1, 0 ), write(var B),
49+ //! t2: (0,y) , atomic[acquire A], t2=(x+1, y+1), ,write(var B)
50+ //!
51+ //! The timestamp is not incremented before an atomic operation, since the result is indistinguishable
52+ //! from the value not being incremented.
53+ //! t: (x, 0), atomic[release _], (x + 1, 0) || (0, y), atomic[acquire _], (x, _)
54+ //! vs t: (x, 0), atomic[release _], (x + 1, 0) || (0, y), atomic[acquire _], (x+1, _)
55+ //! Both result in the sequence on thread x up to and including the atomic release as happening
56+ //! before the acquire.
57+ //!
4058//! FIXME:
4159//! currently we have our own local copy of the currently active thread index and names, this is due
4260//! in part to the inability to access the current location of threads.active_thread inside the AllocExtra
@@ -499,7 +517,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
499517 }
500518
501519 /// Perform an atomic compare and exchange at a given memory location
502- /// on success an atomic RMW operation is performed and on failure
520+ /// On success an atomic RMW operation is performed and on failure
503521 /// only an atomic read occurs.
504522 fn atomic_compare_exchange_scalar (
505523 & mut self ,
@@ -1136,9 +1154,6 @@ impl GlobalState {
11361154 // Now load the two clocks and configure the initial state.
11371155 let ( current, created) = vector_clocks. pick2_mut ( current_index, created_index) ;
11381156
1139- // Advance the current thread before the synchronized operation.
1140- current. increment_clock ( current_index) ;
1141-
11421157 // Join the created with current, since the current threads
11431158 // previous actions happen-before the created thread.
11441159 created. join_with ( current) ;
@@ -1167,14 +1182,12 @@ impl GlobalState {
11671182 . as_ref ( )
11681183 . expect ( "Joined with thread but thread has not terminated" ) ;
11691184
1170- // Pre increment clocks before atomic operation.
1171- current. increment_clock ( current_index) ;
11721185
11731186 // The join thread happens-before the current thread
11741187 // so update the current vector clock.
11751188 current. clock . join ( join_clock) ;
11761189
1177- // Post increment clocks after atomic operation.
1190+ // Increment clocks after atomic operation.
11781191 current. increment_clock ( current_index) ;
11791192
11801193 // Check the number of active threads, if the value is 1
@@ -1277,8 +1290,7 @@ impl GlobalState {
12771290 op : impl FnOnce ( VectorIdx , RefMut < ' _ , ThreadClockSet > ) -> InterpResult < ' tcx > ,
12781291 ) -> InterpResult < ' tcx > {
12791292 if self . multi_threaded . get ( ) {
1280- let ( index, mut clocks) = self . current_thread_state_mut ( ) ;
1281- clocks. increment_clock ( index) ;
1293+ let ( index, clocks) = self . current_thread_state_mut ( ) ;
12821294 op ( index, clocks) ?;
12831295 let ( _, mut clocks) = self . current_thread_state_mut ( ) ;
12841296 clocks. increment_clock ( index) ;
@@ -1303,16 +1315,18 @@ impl GlobalState {
13031315 /// `validate_lock_release` must happen before this.
13041316 pub fn validate_lock_acquire ( & self , lock : & VClock , thread : ThreadId ) {
13051317 let ( index, mut clocks) = self . load_thread_state_mut ( thread) ;
1306- clocks. increment_clock ( index) ;
13071318 clocks. clock . join ( & lock) ;
13081319 clocks. increment_clock ( index) ;
13091320 }
13101321
13111322 /// Release a lock handle, express that this happens-before
13121323 /// any subsequent calls to `validate_lock_acquire`.
1324+ /// For normal locks this should be equivalent to `validate_lock_release_shared`
1325+ /// since an acquire operation should have occured before, however
1326+ /// for futex & cond-var operations this is not the case and this
1327+ /// operation must be used.
13131328 pub fn validate_lock_release ( & self , lock : & mut VClock , thread : ThreadId ) {
13141329 let ( index, mut clocks) = self . load_thread_state_mut ( thread) ;
1315- clocks. increment_clock ( index) ;
13161330 lock. clone_from ( & clocks. clock ) ;
13171331 clocks. increment_clock ( index) ;
13181332 }
@@ -1321,9 +1335,11 @@ impl GlobalState {
13211335 /// any subsequent calls to `validate_lock_acquire` as well
13221336 /// as any previous calls to this function after any
13231337 /// `validate_lock_release` calls.
1338+ /// For normal locks this should be equivalent to `validate_lock_release`
1339+ /// this function only exists for joining over the set of concurrent readers
1340+ /// in a read-write lock and should not be used for anything else.
13241341 pub fn validate_lock_release_shared ( & self , lock : & mut VClock , thread : ThreadId ) {
13251342 let ( index, mut clocks) = self . load_thread_state_mut ( thread) ;
1326- clocks. increment_clock ( index) ;
13271343 lock. join ( & clocks. clock ) ;
13281344 clocks. increment_clock ( index) ;
13291345 }
0 commit comments