@@ -220,25 +220,22 @@ impl WriteType {
220
220
/// for data-race detection.
221
221
#[ derive( Clone , PartialEq , Eq , Debug ) ]
222
222
struct MemoryCellClocks {
223
- /// The vector-clock timestamp of the last write
224
- /// corresponding to the writing threads timestamp.
225
- write : VTimestamp ,
226
-
227
- /// The identifier of the vector index, corresponding to a thread
228
- /// that performed the last write operation.
229
- write_index : VectorIdx ,
223
+ /// The vector-clock timestamp and the thread that did the last non-atomic write. We don't need
224
+ /// a full `VClock` here, it's always a single thread and nothing synchronizes, so the effective
225
+ /// clock is all-0 except for the thread that did the write.
226
+ write : ( VectorIdx , VTimestamp ) ,
230
227
231
228
/// The type of operation that the write index represents,
232
229
/// either newly allocated memory, a non-atomic write or
233
230
/// a deallocation of memory.
234
231
write_type : WriteType ,
235
232
236
- /// The vector-clock of the timestamp of the last read operation
237
- /// performed by a thread since the last write operation occurred.
238
- /// It is reset to zero on each write operation.
233
+ /// The vector-clock of all non-atomic reads that happened since the last non-atomic write
234
+ /// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to
235
+ /// zero on each write operation.
239
236
read : VClock ,
240
237
241
- /// Atomic acquire & release sequence tracking clocks.
238
+ /// Atomic access, acquire, release sequence tracking clocks.
242
239
/// For non-atomic memory in the common case this
243
240
/// value is set to None.
244
241
atomic_ops : Option < Box < AtomicMemoryCellClocks > > ,
@@ -250,13 +247,24 @@ impl MemoryCellClocks {
250
247
fn new ( alloc : VTimestamp , alloc_index : VectorIdx ) -> Self {
251
248
MemoryCellClocks {
252
249
read : VClock :: default ( ) ,
253
- write : alloc,
254
- write_index : alloc_index,
250
+ write : ( alloc_index, alloc) ,
255
251
write_type : WriteType :: Allocate ,
256
252
atomic_ops : None ,
257
253
}
258
254
}
259
255
256
+ #[ inline]
257
+ fn write_was_before ( & self , other : & VClock ) -> bool {
258
+ // This is the same as `self.write() <= other` but
259
+ // without actually manifesting a clock for `self.write`.
260
+ self . write . 1 <= other[ self . write . 0 ]
261
+ }
262
+
263
+ #[ inline]
264
+ fn write ( & self ) -> VClock {
265
+ VClock :: new_with_index ( self . write . 0 , self . write . 1 )
266
+ }
267
+
260
268
/// Load the internal atomic memory cells if they exist.
261
269
#[ inline]
262
270
fn atomic ( & self ) -> Option < & AtomicMemoryCellClocks > {
@@ -376,7 +384,7 @@ impl MemoryCellClocks {
376
384
log:: trace!( "Atomic read with vectors: {:#?} :: {:#?}" , self , thread_clocks) ;
377
385
let atomic = self . atomic_mut ( ) ;
378
386
atomic. read_vector . set_at_index ( & thread_clocks. clock , index) ;
379
- if self . write <= thread_clocks. clock [ self . write_index ] { Ok ( ( ) ) } else { Err ( DataRace ) }
387
+ if self . write_was_before ( & thread_clocks. clock ) { Ok ( ( ) ) } else { Err ( DataRace ) }
380
388
}
381
389
382
390
/// Detect data-races with an atomic write, either with a non-atomic read or with
@@ -389,7 +397,7 @@ impl MemoryCellClocks {
389
397
log:: trace!( "Atomic write with vectors: {:#?} :: {:#?}" , self , thread_clocks) ;
390
398
let atomic = self . atomic_mut ( ) ;
391
399
atomic. write_vector . set_at_index ( & thread_clocks. clock , index) ;
392
- if self . write <= thread_clocks. clock [ self . write_index ] && self . read <= thread_clocks. clock {
400
+ if self . write_was_before ( & thread_clocks. clock ) && self . read <= thread_clocks. clock {
393
401
Ok ( ( ) )
394
402
} else {
395
403
Err ( DataRace )
@@ -408,7 +416,7 @@ impl MemoryCellClocks {
408
416
if !current_span. is_dummy ( ) {
409
417
thread_clocks. clock [ index] . span = current_span;
410
418
}
411
- if self . write <= thread_clocks. clock [ self . write_index ] {
419
+ if self . write_was_before ( & thread_clocks. clock ) {
412
420
let race_free = if let Some ( atomic) = self . atomic ( ) {
413
421
atomic. write_vector <= thread_clocks. clock
414
422
} else {
@@ -434,15 +442,14 @@ impl MemoryCellClocks {
434
442
if !current_span. is_dummy ( ) {
435
443
thread_clocks. clock [ index] . span = current_span;
436
444
}
437
- if self . write <= thread_clocks. clock [ self . write_index ] && self . read <= thread_clocks. clock {
445
+ if self . write_was_before ( & thread_clocks. clock ) && self . read <= thread_clocks. clock {
438
446
let race_free = if let Some ( atomic) = self . atomic ( ) {
439
447
atomic. write_vector <= thread_clocks. clock
440
448
&& atomic. read_vector <= thread_clocks. clock
441
449
} else {
442
450
true
443
451
} ;
444
- self . write = thread_clocks. clock [ index] ;
445
- self . write_index = index;
452
+ self . write = ( index, thread_clocks. clock [ index] ) ;
446
453
self . write_type = write_type;
447
454
if race_free {
448
455
self . read . set_zero_vector ( ) ;
@@ -790,37 +797,35 @@ impl VClockAlloc {
790
797
) -> InterpResult < ' tcx > {
791
798
let ( current_index, current_clocks) = global. current_thread_state ( thread_mgr) ;
792
799
let write_clock;
793
- let ( other_action, other_thread, other_clock) = if mem_clocks. write
794
- > current_clocks. clock [ mem_clocks. write_index ]
795
- {
796
- // Convert the write action into the vector clock it
797
- // represents for diagnostic purposes.
798
- write_clock = VClock :: new_with_index ( mem_clocks. write_index , mem_clocks. write ) ;
799
- ( mem_clocks. write_type . get_descriptor ( ) , mem_clocks. write_index , & write_clock)
800
- } else if let Some ( idx) = Self :: find_gt_index ( & mem_clocks. read , & current_clocks. clock ) {
801
- ( "Read" , idx, & mem_clocks. read )
802
- } else if !is_atomic {
803
- if let Some ( atomic) = mem_clocks. atomic ( ) {
804
- if let Some ( idx) = Self :: find_gt_index ( & atomic. write_vector , & current_clocks. clock )
805
- {
806
- ( "Atomic Store" , idx, & atomic. write_vector )
807
- } else if let Some ( idx) =
808
- Self :: find_gt_index ( & atomic. read_vector , & current_clocks. clock )
809
- {
810
- ( "Atomic Load" , idx, & atomic. read_vector )
800
+ #[ rustfmt:: skip]
801
+ let ( other_action, other_thread, other_clock) =
802
+ if mem_clocks. write . 1 > current_clocks. clock [ mem_clocks. write . 0 ] {
803
+ write_clock = mem_clocks. write ( ) ;
804
+ ( mem_clocks. write_type . get_descriptor ( ) , mem_clocks. write . 0 , & write_clock)
805
+ } else if let Some ( idx) = Self :: find_gt_index ( & mem_clocks. read , & current_clocks. clock ) {
806
+ ( "Read" , idx, & mem_clocks. read )
807
+ } else if !is_atomic {
808
+ if let Some ( atomic) = mem_clocks. atomic ( ) {
809
+ if let Some ( idx) = Self :: find_gt_index ( & atomic. write_vector , & current_clocks. clock )
810
+ {
811
+ ( "Atomic Store" , idx, & atomic. write_vector )
812
+ } else if let Some ( idx) =
813
+ Self :: find_gt_index ( & atomic. read_vector , & current_clocks. clock )
814
+ {
815
+ ( "Atomic Load" , idx, & atomic. read_vector )
816
+ } else {
817
+ unreachable ! (
818
+ "Failed to report data-race for non-atomic operation: no race found"
819
+ )
820
+ }
811
821
} else {
812
822
unreachable ! (
813
- "Failed to report data-race for non-atomic operation: no race found "
823
+ "Failed to report data-race for non-atomic operation: no atomic component "
814
824
)
815
825
}
816
826
} else {
817
- unreachable ! (
818
- "Failed to report data-race for non-atomic operation: no atomic component"
819
- )
820
- }
821
- } else {
822
- unreachable ! ( "Failed to report data-race for atomic operation" )
823
- } ;
827
+ unreachable ! ( "Failed to report data-race for atomic operation" )
828
+ } ;
824
829
825
830
// Load elaborated thread information about the racing thread actions.
826
831
let current_thread_info = global. print_thread_metadata ( thread_mgr, current_index) ;
0 commit comments