diff options
| author | bors <bors@rust-lang.org> | 2023-08-18 19:03:38 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-08-18 19:03:38 +0000 |
| commit | d06ca0ffaf4ac72732665f99dd9ad962194cd0b3 (patch) | |
| tree | 1b6580c5664d6689388b4ec11d9501cf40c12733 /library/std/src | |
| parent | ee5cb9e3a608b58a21889c77733564b48b74544f (diff) | |
| parent | fd9fcc580a40bdf398576199c5e8c3ebe12de9c6 (diff) | |
| download | rust-d06ca0ffaf4ac72732665f99dd9ad962194cd0b3.tar.gz rust-d06ca0ffaf4ac72732665f99dd9ad962194cd0b3.zip | |
Auto merge of #114591 - joboet:thread_parking_ordering_fix, r=thomcc
Synchronize with all calls to `unpark` in id-based thread parker [The documentation for `thread::park`](https://doc.rust-lang.org/nightly/std/thread/fn.park.html#memory-ordering) guarantees that "park synchronizes-with all prior unpark operations". In the id-based thread parking implementation, this is not implemented correctly, as the state variable is reset with a simple store, so there will not be a *synchronizes-with* edge if an `unpark` happens just before the reset. This PR corrects this, replacing the load-check-reset sequence with a single `compare_exchange`.
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/sys_common/thread_parking/id.rs | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs index 15042fc3bee..04667439660 100644 --- a/library/std/src/sys_common/thread_parking/id.rs +++ b/library/std/src/sys_common/thread_parking/id.rs @@ -56,18 +56,14 @@ impl Parker { self.init_tid(); // Changes NOTIFIED to EMPTY and EMPTY to PARKED. - let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); - if state == PARKED { + let state = self.state.fetch_sub(1, Acquire); + if state == EMPTY { // Loop to guard against spurious wakeups. - while state == PARKED { + // The state must be reset with acquire ordering to ensure that all + // calls to `unpark` synchronize with this thread. + while self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed).is_err() { park(self.state.as_ptr().addr()); - state = self.state.load(Acquire); } - - // Since the state change has already been observed with acquire - // ordering, the state can be reset with a relaxed store instead - // of a swap. - self.state.store(EMPTY, Relaxed); } } @@ -78,8 +74,7 @@ impl Parker { if state == PARKED { park_timeout(dur, self.state.as_ptr().addr()); // Swap to ensure that we observe all state changes with acquire - // ordering, even if the state has been changed after the timeout - // occurred. + // ordering. self.state.swap(EMPTY, Acquire); } } |
