@@ -47,7 +47,7 @@ use std::{
47
47
} ;
48
48
49
49
use rustc_ast:: Mutability ;
50
- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
50
+ use rustc_data_structures:: fx:: FxHashSet ;
51
51
use rustc_index:: { Idx , IndexVec } ;
52
52
use rustc_middle:: { mir, ty:: Ty } ;
53
53
use rustc_span:: Span ;
@@ -822,6 +822,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
822
822
assert ! ( !old, "cannot nest allow_data_races" ) ;
823
823
}
824
824
}
825
+
826
+ /// Returns the `release` clock of the current thread.
827
+ /// Other threads can acquire this clock in the future to establish synchronization
828
+ /// with this program point.
829
+ fn release_clock < ' a > ( & ' a self ) -> Option < Ref < ' a , VClock > >
830
+ where
831
+ ' mir : ' a ,
832
+ {
833
+ let this = self . eval_context_ref ( ) ;
834
+ Some ( this. machine . data_race . as_ref ( ) ?. release_clock ( & this. machine . threads ) )
835
+ }
836
+
837
+ /// Acquire the given clock into the current thread, establishing synchronization with
838
+ /// the moment when that clock snapshot was taken via `release_clock`.
839
+ fn acquire_clock ( & self , clock : & VClock ) {
840
+ let this = self . eval_context_ref ( ) ;
841
+ if let Some ( data_race) = & this. machine . data_race {
842
+ data_race. acquire_clock ( clock, & this. machine . threads ) ;
843
+ }
844
+ }
825
845
}
826
846
827
847
/// Vector clock metadata for a logical memory allocation.
@@ -1412,13 +1432,6 @@ pub struct GlobalState {
1412
1432
/// active vector-clocks catch up with the threads timestamp.
1413
1433
reuse_candidates : RefCell < FxHashSet < VectorIdx > > ,
1414
1434
1415
- /// This contains threads that have terminated, but not yet joined
1416
- /// and so cannot become re-use candidates until a join operation
1417
- /// occurs.
1418
- /// The associated vector index will be moved into re-use candidates
1419
- /// after the join operation occurs.
1420
- terminated_threads : RefCell < FxHashMap < ThreadId , VectorIdx > > ,
1421
-
1422
1435
/// The timestamp of last SC fence performed by each thread
1423
1436
last_sc_fence : RefCell < VClock > ,
1424
1437
@@ -1446,7 +1459,6 @@ impl GlobalState {
1446
1459
vector_info : RefCell :: new ( IndexVec :: new ( ) ) ,
1447
1460
thread_info : RefCell :: new ( IndexVec :: new ( ) ) ,
1448
1461
reuse_candidates : RefCell :: new ( FxHashSet :: default ( ) ) ,
1449
- terminated_threads : RefCell :: new ( FxHashMap :: default ( ) ) ,
1450
1462
last_sc_fence : RefCell :: new ( VClock :: default ( ) ) ,
1451
1463
last_sc_write : RefCell :: new ( VClock :: default ( ) ) ,
1452
1464
track_outdated_loads : config. track_outdated_loads ,
@@ -1480,8 +1492,6 @@ impl GlobalState {
1480
1492
fn find_vector_index_reuse_candidate ( & self ) -> Option < VectorIdx > {
1481
1493
let mut reuse = self . reuse_candidates . borrow_mut ( ) ;
1482
1494
let vector_clocks = self . vector_clocks . borrow ( ) ;
1483
- let vector_info = self . vector_info . borrow ( ) ;
1484
- let terminated_threads = self . terminated_threads . borrow ( ) ;
1485
1495
for & candidate in reuse. iter ( ) {
1486
1496
let target_timestamp = vector_clocks[ candidate] . clock [ candidate] ;
1487
1497
if vector_clocks. iter_enumerated ( ) . all ( |( clock_idx, clock) | {
@@ -1491,9 +1501,7 @@ impl GlobalState {
1491
1501
1492
1502
// The vector represents a thread that has terminated and hence cannot
1493
1503
// report a data-race with the candidate index.
1494
- let thread_id = vector_info[ clock_idx] ;
1495
- let vector_terminated =
1496
- reuse. contains ( & clock_idx) || terminated_threads. contains_key ( & thread_id) ;
1504
+ let vector_terminated = reuse. contains ( & clock_idx) ;
1497
1505
1498
1506
// The vector index cannot report a race with the candidate index
1499
1507
// and hence allows the candidate index to be re-used.
@@ -1583,55 +1591,38 @@ impl GlobalState {
1583
1591
/// thread (the joinee, the thread that someone waited on) and the current thread (the joiner,
1584
1592
/// the thread who was waiting).
1585
1593
#[ inline]
1586
- pub fn thread_joined (
1587
- & mut self ,
1588
- thread_mgr : & ThreadManager < ' _ , ' _ > ,
1589
- joiner : ThreadId ,
1590
- joinee : ThreadId ,
1591
- ) {
1592
- let clocks_vec = self . vector_clocks . get_mut ( ) ;
1593
- let thread_info = self . thread_info . get_mut ( ) ;
1594
-
1595
- // Load the vector clock of the current thread.
1596
- let current_index = thread_info[ joiner]
1597
- . vector_index
1598
- . expect ( "Performed thread join on thread with no assigned vector" ) ;
1599
- let current = & mut clocks_vec[ current_index] ;
1594
+ pub fn thread_joined ( & mut self , threads : & ThreadManager < ' _ , ' _ > , joinee : ThreadId ) {
1595
+ let thread_info = self . thread_info . borrow ( ) ;
1596
+ let thread_info = & thread_info[ joinee] ;
1600
1597
1601
1598
// Load the associated vector clock for the terminated thread.
1602
- let join_clock = thread_info[ joinee ]
1599
+ let join_clock = thread_info
1603
1600
. termination_vector_clock
1604
1601
. as_ref ( )
1605
- . expect ( "Joined with thread but thread has not terminated" ) ;
1606
-
1607
- // The join thread happens-before the current thread
1608
- // so update the current vector clock.
1609
- // Is not a release operation so the clock is not incremented.
1610
- current. clock . join ( join_clock) ;
1602
+ . expect ( "joined with thread but thread has not terminated" ) ;
1603
+ // Acquire that into the current thread.
1604
+ self . acquire_clock ( join_clock, threads) ;
1611
1605
1612
1606
// Check the number of live threads, if the value is 1
1613
1607
// then test for potentially disabling multi-threaded execution.
1614
- if thread_mgr. get_live_thread_count ( ) == 1 {
1615
- // May potentially be able to disable multi-threaded execution.
1616
- let current_clock = & clocks_vec[ current_index] ;
1617
- if clocks_vec
1618
- . iter_enumerated ( )
1619
- . all ( |( idx, clocks) | clocks. clock [ idx] <= current_clock. clock [ idx] )
1620
- {
1621
- // All thread terminations happen-before the current clock
1622
- // therefore no data-races can be reported until a new thread
1623
- // is created, so disable multi-threaded execution.
1624
- self . multi_threaded . set ( false ) ;
1608
+ // This has to happen after `acquire_clock`, otherwise there'll always
1609
+ // be some thread that has not synchronized yet.
1610
+ if let Some ( current_index) = thread_info. vector_index {
1611
+ if threads. get_live_thread_count ( ) == 1 {
1612
+ let vector_clocks = self . vector_clocks . get_mut ( ) ;
1613
+ // May potentially be able to disable multi-threaded execution.
1614
+ let current_clock = & vector_clocks[ current_index] ;
1615
+ if vector_clocks
1616
+ . iter_enumerated ( )
1617
+ . all ( |( idx, clocks) | clocks. clock [ idx] <= current_clock. clock [ idx] )
1618
+ {
1619
+ // All thread terminations happen-before the current clock
1620
+ // therefore no data-races can be reported until a new thread
1621
+ // is created, so disable multi-threaded execution.
1622
+ self . multi_threaded . set ( false ) ;
1623
+ }
1625
1624
}
1626
1625
}
1627
-
1628
- // If the thread is marked as terminated but not joined
1629
- // then move the thread to the re-use set.
1630
- let termination = self . terminated_threads . get_mut ( ) ;
1631
- if let Some ( index) = termination. remove ( & joinee) {
1632
- let reuse = self . reuse_candidates . get_mut ( ) ;
1633
- reuse. insert ( index) ;
1634
- }
1635
1626
}
1636
1627
1637
1628
/// On thread termination, the vector-clock may re-used
@@ -1642,29 +1633,18 @@ impl GlobalState {
1642
1633
/// This should be called strictly before any calls to
1643
1634
/// `thread_joined`.
1644
1635
#[ inline]
1645
- pub fn thread_terminated ( & mut self , thread_mgr : & ThreadManager < ' _ , ' _ > , current_span : Span ) {
1636
+ pub fn thread_terminated ( & mut self , thread_mgr : & ThreadManager < ' _ , ' _ > ) {
1637
+ let current_thread = thread_mgr. active_thread ( ) ;
1646
1638
let current_index = self . active_thread_index ( thread_mgr) ;
1647
1639
1648
- // Increment the clock to a unique termination timestamp.
1649
- let vector_clocks = self . vector_clocks . get_mut ( ) ;
1650
- let current_clocks = & mut vector_clocks[ current_index] ;
1651
- current_clocks. increment_clock ( current_index, current_span) ;
1652
-
1653
- // Load the current thread id for the executing vector.
1654
- let vector_info = self . vector_info . get_mut ( ) ;
1655
- let current_thread = vector_info[ current_index] ;
1656
-
1657
- // Load the current thread metadata, and move to a terminated
1658
- // vector state. Setting up the vector clock all join operations
1659
- // will use.
1660
- let thread_info = self . thread_info . get_mut ( ) ;
1661
- let current = & mut thread_info[ current_thread] ;
1662
- current. termination_vector_clock = Some ( current_clocks. clock . clone ( ) ) ;
1640
+ // Store the terminaion clock.
1641
+ let terminaion_clock = self . release_clock ( thread_mgr) . clone ( ) ;
1642
+ self . thread_info . get_mut ( ) [ current_thread] . termination_vector_clock =
1643
+ Some ( terminaion_clock) ;
1663
1644
1664
- // Add this thread as a candidate for re-use after a thread join
1665
- // occurs.
1666
- let termination = self . terminated_threads . get_mut ( ) ;
1667
- termination. insert ( current_thread, current_index) ;
1645
+ // Add this thread's clock index as a candidate for re-use.
1646
+ let reuse = self . reuse_candidates . get_mut ( ) ;
1647
+ reuse. insert ( current_index) ;
1668
1648
}
1669
1649
1670
1650
/// Attempt to perform a synchronized operation, this
@@ -1702,23 +1682,29 @@ impl GlobalState {
1702
1682
format ! ( "thread `{thread_name}`" )
1703
1683
}
1704
1684
1705
- /// Acquire the given clock into the given thread, establishing synchronization with
1685
+ /// Acquire the given clock into the current thread, establishing synchronization with
1706
1686
/// the moment when that clock snapshot was taken via `release_clock`.
1707
1687
/// As this is an acquire operation, the thread timestamp is not
1708
1688
/// incremented.
1709
- pub fn acquire_clock ( & self , lock : & VClock , thread : ThreadId ) {
1689
+ pub fn acquire_clock < ' mir , ' tcx > ( & self , clock : & VClock , threads : & ThreadManager < ' mir , ' tcx > ) {
1690
+ let thread = threads. active_thread ( ) ;
1710
1691
let ( _, mut clocks) = self . thread_state_mut ( thread) ;
1711
- clocks. clock . join ( lock ) ;
1692
+ clocks. clock . join ( clock ) ;
1712
1693
}
1713
1694
1714
- /// Returns the `release` clock of the given thread.
1695
+ /// Returns the `release` clock of the current thread.
1715
1696
/// Other threads can acquire this clock in the future to establish synchronization
1716
1697
/// with this program point.
1717
- pub fn release_clock ( & self , thread : ThreadId , current_span : Span ) -> Ref < ' _ , VClock > {
1698
+ pub fn release_clock < ' mir , ' tcx > (
1699
+ & self ,
1700
+ threads : & ThreadManager < ' mir , ' tcx > ,
1701
+ ) -> Ref < ' _ , VClock > {
1702
+ let thread = threads. active_thread ( ) ;
1703
+ let span = threads. active_thread_ref ( ) . current_span ( ) ;
1718
1704
// We increment the clock each time this happens, to ensure no two releases
1719
1705
// can be confused with each other.
1720
1706
let ( index, mut clocks) = self . thread_state_mut ( thread) ;
1721
- clocks. increment_clock ( index, current_span ) ;
1707
+ clocks. increment_clock ( index, span ) ;
1722
1708
drop ( clocks) ;
1723
1709
// To return a read-only view, we need to release the RefCell
1724
1710
// and borrow it again.
@@ -1757,7 +1743,7 @@ impl GlobalState {
1757
1743
& self ,
1758
1744
thread_mgr : & ThreadManager < ' _ , ' _ > ,
1759
1745
) -> ( VectorIdx , Ref < ' _ , ThreadClockSet > ) {
1760
- self . thread_state ( thread_mgr. get_active_thread_id ( ) )
1746
+ self . thread_state ( thread_mgr. active_thread ( ) )
1761
1747
}
1762
1748
1763
1749
/// Load the current vector clock in use and the current set of thread clocks
@@ -1767,14 +1753,14 @@ impl GlobalState {
1767
1753
& self ,
1768
1754
thread_mgr : & ThreadManager < ' _ , ' _ > ,
1769
1755
) -> ( VectorIdx , RefMut < ' _ , ThreadClockSet > ) {
1770
- self . thread_state_mut ( thread_mgr. get_active_thread_id ( ) )
1756
+ self . thread_state_mut ( thread_mgr. active_thread ( ) )
1771
1757
}
1772
1758
1773
1759
/// Return the current thread, should be the same
1774
1760
/// as the data-race active thread.
1775
1761
#[ inline]
1776
1762
fn active_thread_index ( & self , thread_mgr : & ThreadManager < ' _ , ' _ > ) -> VectorIdx {
1777
- let active_thread_id = thread_mgr. get_active_thread_id ( ) ;
1763
+ let active_thread_id = thread_mgr. active_thread ( ) ;
1778
1764
self . thread_index ( active_thread_id)
1779
1765
}
1780
1766
0 commit comments