about summary refs log tree commit diff
path: root/src/libstd/thread
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-10-31 13:52:00 +0000
committerbors <bors@rust-lang.org>2018-10-31 13:52:00 +0000
commitde9666f123e800d5fc34210f23127aa6a5d6e4ef (patch)
treee940ed377031f48227e7610a0408d34164883049 /src/libstd/thread
parent05812fa8c588473f03e3fa7cf59cd84f4f37c715 (diff)
parentd3e71e4986c3970d2f51b972c1dfdd740f89385a (diff)
downloadrust-de9666f123e800d5fc34210f23127aa6a5d6e4ef.tar.gz
rust-de9666f123e800d5fc34210f23127aa6a5d6e4ef.zip
Auto merge of #54806 - parched:park, r=RalfJung
thread::unpark: Avoid notifying with mutex locked.

This means when the other thread wakes it can continue right away
instead of having to wait for the mutex.

Also add some comments explaining why the mutex needs to be locked in
the first place.

This is a follow up to https://github.com/rust-lang/rust/pull/54174
I did some tests with relacy [here](https://gist.github.com/parched/b7fb88c97755a81e5cb9f9048a15f7fb) (This PR is InnerV2). If anyone can think of some other test case worth adding let me know.

r? @RalfJung
Diffstat (limited to 'src/libstd/thread')
-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 3702c91966f..a57b8dc7237 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -1149,8 +1149,18 @@ impl Thread {
             _ => panic!("inconsistent state in unpark"),
         }
 
-        // Coordinate wakeup through the mutex and a condvar notification
-        let _lock = self.inner.lock.lock().unwrap();
+        // There is a period between when the parked thread sets `state` to
+        // `PARKED` (or last checked `state` in the case of a spurious wake
+        // up) and when it actually waits on `cvar`. If we were to notify
+        // during this period it would be ignored and then when the parked
+        // thread went to sleep it would never wake up. Fortunately, it has
+        // `lock` locked at this stage so we can acquire `lock` to wait until
+        // it is ready to receive the notification.
+        //
+        // Releasing `lock` before the call to `notify_one` means that when the
+        // parked thread wakes it doesn't get woken only to have to wait for us
+        // to release `lock`.
+        drop(self.inner.lock.lock().unwrap());
         self.inner.cvar.notify_one()
     }