-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix thread
park
/unpark
synchronization
#54174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -800,7 +800,7 @@ pub fn park() { | |
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { | ||
Ok(_) => {} | ||
Err(NOTIFIED) => { | ||
thread.inner.state.store(EMPTY, SeqCst); | ||
thread.inner.state.swap(EMPTY, SeqCst); | ||
return; | ||
} // should consume this notification, so prohibit spurious wakeups in next park. | ||
Err(_) => panic!("inconsistent park state"), | ||
|
@@ -889,7 +889,7 @@ pub fn park_timeout(dur: Duration) { | |
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { | ||
Ok(_) => {} | ||
Err(NOTIFIED) => { | ||
thread.inner.state.store(EMPTY, SeqCst); | ||
thread.inner.state.swap(EMPTY, SeqCst); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a comment that why |
||
return; | ||
} // should consume this notification, so prohibit spurious wakeups in next park. | ||
Err(_) => panic!("inconsistent park_timeout state"), | ||
|
@@ -1058,23 +1058,16 @@ impl Thread { | |
/// [park]: fn.park.html | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub fn unpark(&self) { | ||
loop { | ||
match self.inner.state.compare_exchange(EMPTY, NOTIFIED, SeqCst, SeqCst) { | ||
Ok(_) => return, // no one was waiting | ||
Err(NOTIFIED) => return, // already unparked | ||
Err(PARKED) => {} // gotta go wake someone up | ||
_ => panic!("inconsistent state in unpark"), | ||
} | ||
|
||
// Coordinate wakeup through the mutex and a condvar notification | ||
let _lock = self.inner.lock.lock().unwrap(); | ||
match self.inner.state.compare_exchange(PARKED, NOTIFIED, SeqCst, SeqCst) { | ||
Ok(_) => return self.inner.cvar.notify_one(), | ||
Err(NOTIFIED) => return, // a different thread unparked | ||
Err(EMPTY) => {} // parked thread went away, try again | ||
_ => panic!("inconsistent state in unpark"), | ||
} | ||
match self.inner.state.swap(NOTIFIED, SeqCst) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's worth adding a comment saying that even if the thread is already notified, we still want to do a write with |
||
EMPTY => return, // no one was waiting | ||
NOTIFIED => return, // already unparked | ||
PARKED => {} // gotta go wake someone up | ||
_ => panic!("inconsistent state in unpark"), | ||
} | ||
|
||
// Coordinate wakeup through the mutex and a condvar notification | ||
let _lock = self.inner.lock.lock().unwrap(); | ||
self.inner.cvar.notify_one() | ||
} | ||
|
||
/// Gets the thread's unique identifier. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if this should be a .compare_exchange().unwrap(), just to be more explicit and make some use of the read value (thus possibly reducing the chance of somebody changing this back to .store() in the future). This shouldn't be a common case so I don't imagine the performance impact would be very noticeable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree, I will add a comment and an assertion.