@@ -47,7 +47,7 @@ use std::{
4747} ;
4848
4949use rustc_ast:: Mutability ;
50- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
50+ use rustc_data_structures:: fx:: FxHashSet ;
5151use rustc_index:: { Idx , IndexVec } ;
5252use rustc_middle:: { mir, ty:: Ty } ;
5353use rustc_span:: Span ;
@@ -822,6 +822,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
822822 assert ! ( !old, "cannot nest allow_data_races" ) ;
823823 }
824824 }
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+ }
825845}
826846
827847/// Vector clock metadata for a logical memory allocation.
@@ -1412,13 +1432,6 @@ pub struct GlobalState {
14121432 /// active vector-clocks catch up with the threads timestamp.
14131433 reuse_candidates : RefCell < FxHashSet < VectorIdx > > ,
14141434
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-
14221435 /// The timestamp of last SC fence performed by each thread
14231436 last_sc_fence : RefCell < VClock > ,
14241437
@@ -1446,7 +1459,6 @@ impl GlobalState {
14461459 vector_info : RefCell :: new ( IndexVec :: new ( ) ) ,
14471460 thread_info : RefCell :: new ( IndexVec :: new ( ) ) ,
14481461 reuse_candidates : RefCell :: new ( FxHashSet :: default ( ) ) ,
1449- terminated_threads : RefCell :: new ( FxHashMap :: default ( ) ) ,
14501462 last_sc_fence : RefCell :: new ( VClock :: default ( ) ) ,
14511463 last_sc_write : RefCell :: new ( VClock :: default ( ) ) ,
14521464 track_outdated_loads : config. track_outdated_loads ,
@@ -1480,8 +1492,6 @@ impl GlobalState {
14801492 fn find_vector_index_reuse_candidate ( & self ) -> Option < VectorIdx > {
14811493 let mut reuse = self . reuse_candidates . borrow_mut ( ) ;
14821494 let vector_clocks = self . vector_clocks . borrow ( ) ;
1483- let vector_info = self . vector_info . borrow ( ) ;
1484- let terminated_threads = self . terminated_threads . borrow ( ) ;
14851495 for & candidate in reuse. iter ( ) {
14861496 let target_timestamp = vector_clocks[ candidate] . clock [ candidate] ;
14871497 if vector_clocks. iter_enumerated ( ) . all ( |( clock_idx, clock) | {
@@ -1491,9 +1501,7 @@ impl GlobalState {
14911501
14921502 // The vector represents a thread that has terminated and hence cannot
14931503 // 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) ;
14971505
14981506 // The vector index cannot report a race with the candidate index
14991507 // and hence allows the candidate index to be re-used.
@@ -1583,55 +1591,38 @@ impl GlobalState {
15831591 /// thread (the joinee, the thread that someone waited on) and the current thread (the joiner,
15841592 /// the thread who was waiting).
15851593 #[ 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] ;
16001597
16011598 // Load the associated vector clock for the terminated thread.
1602- let join_clock = thread_info[ joinee ]
1599+ let join_clock = thread_info
16031600 . termination_vector_clock
16041601 . 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) ;
16111605
16121606 // Check the number of live threads, if the value is 1
16131607 // 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+ }
16251624 }
16261625 }
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- }
16351626 }
16361627
16371628 /// On thread termination, the vector-clock may re-used
@@ -1642,29 +1633,18 @@ impl GlobalState {
16421633 /// This should be called strictly before any calls to
16431634 /// `thread_joined`.
16441635 #[ 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 ( ) ;
16461638 let current_index = self . active_thread_index ( thread_mgr) ;
16471639
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) ;
16631644
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) ;
16681648 }
16691649
16701650 /// Attempt to perform a synchronized operation, this
@@ -1702,23 +1682,29 @@ impl GlobalState {
17021682 format ! ( "thread `{thread_name}`" )
17031683 }
17041684
1705- /// Acquire the given clock into the given thread, establishing synchronization with
1685+ /// Acquire the given clock into the current thread, establishing synchronization with
17061686 /// the moment when that clock snapshot was taken via `release_clock`.
17071687 /// As this is an acquire operation, the thread timestamp is not
17081688 /// 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 ( ) ;
17101691 let ( _, mut clocks) = self . thread_state_mut ( thread) ;
1711- clocks. clock . join ( lock ) ;
1692+ clocks. clock . join ( clock ) ;
17121693 }
17131694
1714- /// Returns the `release` clock of the given thread.
1695+ /// Returns the `release` clock of the current thread.
17151696 /// Other threads can acquire this clock in the future to establish synchronization
17161697 /// 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 ( ) ;
17181704 // We increment the clock each time this happens, to ensure no two releases
17191705 // can be confused with each other.
17201706 let ( index, mut clocks) = self . thread_state_mut ( thread) ;
1721- clocks. increment_clock ( index, current_span ) ;
1707+ clocks. increment_clock ( index, span ) ;
17221708 drop ( clocks) ;
17231709 // To return a read-only view, we need to release the RefCell
17241710 // and borrow it again.
@@ -1757,7 +1743,7 @@ impl GlobalState {
17571743 & self ,
17581744 thread_mgr : & ThreadManager < ' _ , ' _ > ,
17591745 ) -> ( VectorIdx , Ref < ' _ , ThreadClockSet > ) {
1760- self . thread_state ( thread_mgr. get_active_thread_id ( ) )
1746+ self . thread_state ( thread_mgr. active_thread ( ) )
17611747 }
17621748
17631749 /// Load the current vector clock in use and the current set of thread clocks
@@ -1767,14 +1753,14 @@ impl GlobalState {
17671753 & self ,
17681754 thread_mgr : & ThreadManager < ' _ , ' _ > ,
17691755 ) -> ( VectorIdx , RefMut < ' _ , ThreadClockSet > ) {
1770- self . thread_state_mut ( thread_mgr. get_active_thread_id ( ) )
1756+ self . thread_state_mut ( thread_mgr. active_thread ( ) )
17711757 }
17721758
17731759 /// Return the current thread, should be the same
17741760 /// as the data-race active thread.
17751761 #[ inline]
17761762 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 ( ) ;
17781764 self . thread_index ( active_thread_id)
17791765 }
17801766
0 commit comments