about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJames Duley <james.duley@arm.com>2018-09-14 17:32:16 +0100
committerJames Duley <james.duley@arm.com>2018-09-14 17:35:12 +0100
commitf8a78bdfdfffffe74f516eec4303d7f3d4ac879e (patch)
tree177119e375eee491f5cea6de6cf89c7c9deec1ea /src
parent204d9608e35f7dc56e179d4539e931766fd88f28 (diff)
downloadrust-f8a78bdfdfffffe74f516eec4303d7f3d4ac879e.tar.gz
rust-f8a78bdfdfffffe74f516eec4303d7f3d4ac879e.zip
Add comments and assertion to `park`/`unpark`
regarding the synchronization.
Diffstat (limited to 'src')
-rw-r--r--src/libstd/thread/mod.rs14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 020ea09db2a..1f03ee3e37d 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -800,7 +800,11 @@ pub fn park() {
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
         Err(NOTIFIED) => {
-            thread.inner.state.swap(EMPTY, SeqCst);
+            // We must read again here, even though we know it will be NOTIFY,
+            // to synchronize with an write in `unpark` that occurred since we
+            // last read.
+            let old = thread.inner.state.swap(EMPTY, SeqCst);
+            assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
             return;
         } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park state"),
@@ -889,7 +893,11 @@ pub fn park_timeout(dur: Duration) {
     match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
         Ok(_) => {}
         Err(NOTIFIED) => {
-            thread.inner.state.swap(EMPTY, SeqCst);
+            // We must read again here, even though we know it will be NOTIFY,
+            // to synchronize with an write in `unpark` that occurred since we
+            // last read.
+            let old = thread.inner.state.swap(EMPTY, SeqCst);
+            assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
             return;
         } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park_timeout state"),
@@ -1058,6 +1066,8 @@ impl Thread {
     /// [park]: fn.park.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
+        // We must unconditionally write NOTIFIED here to
+        // synchronize with a read in `park`.
         match self.inner.state.swap(NOTIFIED, SeqCst) {
             EMPTY => return, // no one was waiting
             NOTIFIED => return, // already unparked