@@ -192,6 +192,25 @@ struct AtomicMemoryCellClocks {
192
192
sync_vector : VClock ,
193
193
}
194
194
195
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
196
+ enum WriteType {
197
+ /// Allocate memory.
198
+ Allocate ,
199
+ /// Standard unsynchronized write.
200
+ Write ,
201
+ /// Deallocate memory
202
+ Deallocate ,
203
+ }
204
+ impl WriteType {
205
+ fn get_descriptor ( self ) -> & ' static str {
206
+ match self {
207
+ WriteType :: Allocate => "ALLOCATE" ,
208
+ WriteType :: Write => "WRITE" ,
209
+ WriteType :: Deallocate => "DEALLOCATE" ,
210
+ }
211
+ }
212
+ }
213
+
195
214
/// Memory Cell vector clock metadata
196
215
/// for data-race detection.
197
216
#[ derive( Clone , PartialEq , Eq , Debug ) ]
@@ -204,6 +223,11 @@ struct MemoryCellClocks {
204
223
/// that performed the last write operation.
205
224
write_index : VectorIdx ,
206
225
226
+ /// The type of operation that the write index represents,
227
+ /// either newly allocated memory, a non-atomic write or
228
+ /// a deallocation of memory.
229
+ write_type : WriteType ,
230
+
207
231
/// The vector-clock of the timestamp of the last read operation
208
232
/// performed by a thread since the last write operation occurred.
209
233
/// It is reset to zero on each write operation.
@@ -215,20 +239,19 @@ struct MemoryCellClocks {
215
239
atomic_ops : Option < Box < AtomicMemoryCellClocks > > ,
216
240
}
217
241
218
- /// Create a default memory cell clocks instance
219
- /// for uninitialized memory.
220
- impl Default for MemoryCellClocks {
221
- fn default ( ) -> Self {
242
+ impl MemoryCellClocks {
243
+
244
+ /// Create a new set of clocks representing memory allocated
245
+ /// at a given vector timestamp and index.
246
+ fn new ( alloc : VTimestamp , alloc_index : VectorIdx ) -> Self {
222
247
MemoryCellClocks {
223
248
read : VClock :: default ( ) ,
224
- write : 0 ,
225
- write_index : VectorIdx :: MAX_INDEX ,
249
+ write : alloc,
250
+ write_index : alloc_index,
251
+ write_type : WriteType :: Allocate ,
226
252
atomic_ops : None ,
227
253
}
228
254
}
229
- }
230
-
231
- impl MemoryCellClocks {
232
255
233
256
/// Load the internal atomic memory cells if they exist.
234
257
#[ inline]
@@ -382,6 +405,7 @@ impl MemoryCellClocks {
382
405
& mut self ,
383
406
clocks : & ThreadClockSet ,
384
407
index : VectorIdx ,
408
+ write_type : WriteType ,
385
409
) -> Result < ( ) , DataRace > {
386
410
log:: trace!( "Unsynchronized write with vectors: {:#?} :: {:#?}" , self , clocks) ;
387
411
if self . write <= clocks. clock [ self . write_index ] && self . read <= clocks. clock {
@@ -393,6 +417,7 @@ impl MemoryCellClocks {
393
417
if race_free {
394
418
self . write = clocks. clock [ index] ;
395
419
self . write_index = index;
420
+ self . write_type = write_type;
396
421
self . read . set_zero_vector ( ) ;
397
422
Ok ( ( ) )
398
423
} else {
@@ -646,16 +671,28 @@ pub struct VClockAlloc {
646
671
/// Assigning each byte a MemoryCellClocks.
647
672
alloc_ranges : RefCell < RangeMap < MemoryCellClocks > > ,
648
673
649
- // Pointer to global state.
674
+ /// Pointer to global state.
650
675
global : MemoryExtra ,
651
676
}
652
677
653
678
impl VClockAlloc {
654
- /// Create a new data-race allocation detector.
655
- pub fn new_allocation ( global : & MemoryExtra , len : Size ) -> VClockAlloc {
679
+
680
+ /// Create a new data-race detector for newly allocated memory.
681
+ pub fn new_allocation ( global : & MemoryExtra , len : Size , track_alloc : bool ) -> VClockAlloc {
682
+ //FIXME: stack allocations are currently ignored due to the lazy nature of stack
683
+ // allocation, this results in data-races being missed.
684
+ let ( alloc_timestamp, alloc_index) = if !track_alloc {
685
+ ( 0 , VectorIdx :: MAX_INDEX )
686
+ } else {
687
+ let ( alloc_index, clocks) = global. current_thread_state ( ) ;
688
+ let alloc_timestamp = clocks. clock [ alloc_index] ;
689
+ ( alloc_timestamp, alloc_index)
690
+ } ;
656
691
VClockAlloc {
657
692
global : Rc :: clone ( global) ,
658
- alloc_ranges : RefCell :: new ( RangeMap :: new ( len, MemoryCellClocks :: default ( ) ) ) ,
693
+ alloc_ranges : RefCell :: new ( RangeMap :: new (
694
+ len, MemoryCellClocks :: new ( alloc_timestamp, alloc_index)
695
+ ) ) ,
659
696
}
660
697
}
661
698
@@ -712,7 +749,7 @@ impl VClockAlloc {
712
749
// Convert the write action into the vector clock it
713
750
// represents for diagnostic purposes.
714
751
write_clock = VClock :: new_with_index ( range. write_index , range. write ) ;
715
- ( "WRITE" , range. write_index , & write_clock)
752
+ ( range . write_type . get_descriptor ( ) , range. write_index , & write_clock)
716
753
} else if let Some ( idx) = Self :: find_gt_index ( & range. read , & current_clocks. clock ) {
717
754
( "READ" , idx, & range. read )
718
755
} else if !is_atomic {
@@ -792,17 +829,17 @@ impl VClockAlloc {
792
829
& mut self ,
793
830
pointer : Pointer < Tag > ,
794
831
len : Size ,
795
- action : & str ,
832
+ write_type : WriteType ,
796
833
) -> InterpResult < ' tcx > {
797
834
if self . global . multi_threaded . get ( ) {
798
835
let ( index, clocks) = self . global . current_thread_state ( ) ;
799
836
for ( _, range) in self . alloc_ranges . get_mut ( ) . iter_mut ( pointer. offset , len) {
800
- if let Err ( DataRace ) = range. write_race_detect ( & * clocks, index) {
837
+ if let Err ( DataRace ) = range. write_race_detect ( & * clocks, index, write_type ) {
801
838
// Report data-race
802
839
return Self :: report_data_race (
803
840
& self . global ,
804
841
range,
805
- action ,
842
+ write_type . get_descriptor ( ) ,
806
843
false ,
807
844
pointer,
808
845
len,
@@ -820,15 +857,15 @@ impl VClockAlloc {
820
857
/// being created or if it is temporarily disabled during a racy read or write
821
858
/// operation
822
859
pub fn write < ' tcx > ( & mut self , pointer : Pointer < Tag > , len : Size ) -> InterpResult < ' tcx > {
823
- self . unique_access ( pointer, len, " Write" )
860
+ self . unique_access ( pointer, len, WriteType :: Write )
824
861
}
825
862
826
863
/// Detect data-races for an unsynchronized deallocate operation, will not perform
827
864
/// data-race threads if `multi-threaded` is false, either due to no threads
828
865
/// being created or if it is temporarily disabled during a racy read or write
829
866
/// operation
830
867
pub fn deallocate < ' tcx > ( & mut self , pointer : Pointer < Tag > , len : Size ) -> InterpResult < ' tcx > {
831
- self . unique_access ( pointer, len, " Deallocate" )
868
+ self . unique_access ( pointer, len, WriteType :: Deallocate )
832
869
}
833
870
}
834
871
0 commit comments