Snap for 10453563 from e701e586e5091c8f407ad7fedd5bdaa2c34ba0e2 to mainline-os-statsd-release

Change-Id: I507add8aa2be2022704d18a02aa7e5aabee01901
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 38c6551..ca34d9d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "a75875b0bf904287a9749e8eabea919b5e9dd8a9"
+    "sha1": "336a9b31ff385728d00eb7ef173e4d054584b787"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 4d33593..e5c2395 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -8,6 +8,7 @@
   pull_request:
 
 env:
+  CARGO_INCREMENTAL: 0
   RUST_TEST_THREADS: 1
 
 jobs:
@@ -18,7 +19,7 @@
         os: [ubuntu, macos, windows]
         channel: [1.49.0, stable, beta, nightly]
         feature: [arc_lock, serde, deadlock_detection]
-        exclude: 
+        exclude:
           - feature: deadlock_detection
             channel: '1.49.0'
         include:
@@ -41,7 +42,7 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        target: 
+        target:
           - wasm32-unknown-unknown
           - x86_64-fortanix-unknown-sgx
           #- x86_64-unknown-redox
diff --git a/Android.bp b/Android.bp
index 17f0e2b..6125816 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@
     host_supported: true,
     crate_name: "parking_lot",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.12.0",
+    cargo_pkg_version: "0.12.1",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: ["default"],
@@ -52,8 +52,10 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.virt",
     ],
+    product_available: true,
+    vendor_available: true,
     min_sdk_version: "29",
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1951e9..8421b84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## parking_lot 0.12.1 (2022-05-31)
+
+- Fixed incorrect memory ordering in `RwLock`. (#344)
+- Added `Condvar::wait_while` convenience methods (#343)
+
+## parking_lot_core 0.9.3 (2022-04-30)
+
+- Bump windows-sys dependency to 0.36. (#339)
+
+## parking_lot_core 0.9.2, lock_api 0.4.7 (2022-03-25)
+
+- Enable const new() on lock types on stable. (#325)
+- Added `MutexGuard::leak` function. (#333)
+- Bump windows-sys dependency to 0.34. (#331)
+- Bump petgraph dependency to 0.6. (#326)
+- Don't use pthread attributes on the espidf platform. (#319)
+
+## parking_lot_core 0.9.1 (2022-02-06)
+
+- Bump windows-sys dependency to 0.32. (#316)
+
 ## parking_lot 0.12.0, parking_lot_core 0.9.0, lock_api 0.4.6 (2022-01-28)
 
 - The MSRV is bumped to 1.49.0.
diff --git a/Cargo.toml b/Cargo.toml
index 6f58afa..e474f48 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,19 +12,27 @@
 [package]
 edition = "2018"
 name = "parking_lot"
-version = "0.12.0"
+version = "0.12.1"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 description = "More compact and efficient implementations of the standard synchronization primitives."
 readme = "README.md"
-keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
+keywords = [
+    "mutex",
+    "condvar",
+    "rwlock",
+    "once",
+    "thread",
+]
 categories = ["concurrency"]
-license = "Apache-2.0/MIT"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/Amanieu/parking_lot"
+
 [dependencies.lock_api]
 version = "0.4.6"
 
 [dependencies.parking_lot_core]
 version = "0.9.0"
+
 [dev-dependencies.bincode]
 version = "1.3.3"
 
@@ -36,7 +44,10 @@
 deadlock_detection = ["parking_lot_core/deadlock_detection"]
 default = []
 hardware-lock-elision = []
-nightly = ["parking_lot_core/nightly", "lock_api/nightly"]
+nightly = [
+    "parking_lot_core/nightly",
+    "lock_api/nightly",
+]
 owning_ref = ["lock_api/owning_ref"]
 send_guard = []
 serde = ["lock_api/serde"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index bb501be..90b653d 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,9 +1,9 @@
 [package]
 name = "parking_lot"
-version = "0.12.0"
+version = "0.12.1"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 description = "More compact and efficient implementations of the standard synchronization primitives."
-license = "Apache-2.0/MIT"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/Amanieu/parking_lot"
 readme = "README.md"
 keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
diff --git a/METADATA b/METADATA
index 10f98ed..0cb5945 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/parking_lot
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "parking_lot"
 description: "More compact and efficient implementations of the standard synchronization primitives."
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/parking_lot/parking_lot-0.12.0.crate"
+    value: "https://static.crates.io/crates/parking_lot/parking_lot-0.12.1.crate"
   }
-  version: "0.12.0"
+  version: "0.12.1"
   license_type: NOTICE
   last_upgrade_date {
     year: 2022
-    month: 3
-    day: 1
+    month: 12
+    day: 13
   }
 }
diff --git a/README.md b/README.md
index 5bda8d8..70fdca7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 parking_lot
 ============
 
-![Rust](https://github.com/Amanieu/parking_lot/workflows/Rust/badge.svg)
+[![Rust](https://github.com/Amanieu/parking_lot/workflows/Rust/badge.svg)](https://github.com/Amanieu/parking_lot/actions)
 [![Crates.io](https://img.shields.io/crates/v/parking_lot.svg)](https://crates.io/crates/parking_lot)
 
 [Documentation (synchronization primitives)](https://docs.rs/parking_lot/)
@@ -83,7 +83,7 @@
 based on the Webkit [`WTF::ParkingLot`](https://webkit.org/blog/6161/locking-in-webkit/)
 class, which essentially consists of a hash table mapping of lock addresses
 to queues of parked (sleeping) threads. The Webkit parking lot was itself
-inspired by Linux [futexes](http://man7.org/linux/man-pages/man2/futex.2.html),
+inspired by Linux [futexes](https://man7.org/linux/man-pages/man2/futex.2.html),
 but it is more powerful since it allows invoking callbacks while holding a queue
 lock.
 
@@ -91,11 +91,13 @@
 
 There are a few restrictions when using this library on stable Rust:
 
-- You will have to use the `const_*` functions (e.g. `const_mutex(val)`) to
-  statically initialize the locking primitives. Using e.g. `Mutex::new(val)`
-  does not work on stable Rust yet.
-- The `wasm32-unknown-unknown` target is only supported on nightly and requires
-  `-C target-feature=+atomics` in `RUSTFLAGS`.
+- The `wasm32-unknown-unknown` target is only fully supported on nightly with
+  `-C target-feature=+atomics` in `RUSTFLAGS` and `-Z build-std` passed to cargo.
+  parking_lot will work mostly fine on stable, the only difference is it will
+  panic instead of block forever if you hit a deadlock.
+  Just make sure not to enable `-C target-feature=+atomics` on stable as that
+  will allow wasm to run with multiple threads which will completely break
+  parking_lot's concurrency guarantees.
 
 To enable nightly-only functionality, you need to enable the `nightly` feature
 in Cargo (see below).
@@ -106,14 +108,14 @@
 
 ```toml
 [dependencies]
-parking_lot = "0.11"
+parking_lot = "0.12"
 ```
 
 To enable nightly-only features, add this to your `Cargo.toml` instead:
 
 ```toml
 [dependencies]
-parking_lot = { version = "0.11", features = ["nightly"] }
+parking_lot = { version = "0.12", features = ["nightly"] }
 ```
 
 The experimental deadlock detector can be enabled with the
@@ -142,8 +144,8 @@
 
 Licensed under either of
 
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
 
 at your option.
 
diff --git a/cargo2android.json b/cargo2android.json
index e48e3b8..f994fab 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,7 +1,7 @@
 {
   "apex-available": [
     "//apex_available:platform",
-    "com.android.bluetooth",
+    "com.android.btservices",
     "com.android.virt"
   ],
   "device": true,
diff --git a/src/condvar.rs b/src/condvar.rs
index 9eaf300..15daa69 100644
--- a/src/condvar.rs
+++ b/src/condvar.rs
@@ -14,6 +14,7 @@
 };
 use lock_api::RawMutex as RawMutex_;
 use parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN};
+use std::ops::DerefMut;
 use std::time::{Duration, Instant};
 
 /// A type indicating whether a timed wait on a condition variable returned
@@ -53,7 +54,7 @@
 ///   woken up.
 /// - Only requires 1 word of space, whereas the standard library boxes the
 ///   `Condvar` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
 /// - Does not require any drop glue when dropped.
 /// - Inline fast path for the uncontended case.
 ///
@@ -136,10 +137,9 @@
 
     #[cold]
     fn notify_one_slow(&self, mutex: *mut RawMutex) -> bool {
-        unsafe {
-            // Unpark one thread and requeue the rest onto the mutex
-            let from = self as *const _ as usize;
-            let to = mutex as usize;
+        // Unpark one thread and requeue the rest onto the mutex
+        let from = self as *const _ as usize;
+        let to = mutex as usize;
             let validate = || {
                 // Make sure that our atomic state still points to the same
                 // mutex. If not then it means that all threads on the current
@@ -156,7 +156,7 @@
                 // locking the queue. There is the possibility of a race if the
                 // mutex gets locked after we check, but that doesn't matter in
                 // this case.
-                if (*mutex).mark_parked_if_locked() {
+                if unsafe { (*mutex).mark_parked_if_locked() } {
                     RequeueOp::RequeueOne
                 } else {
                     RequeueOp::UnparkOne
@@ -169,10 +169,9 @@
                 }
                 TOKEN_NORMAL
             };
-            let res = parking_lot_core::unpark_requeue(from, to, validate, callback);
+            let res = unsafe { parking_lot_core::unpark_requeue(from, to, validate, callback) };
 
             res.unparked_threads + res.requeued_threads != 0
-        }
     }
 
     /// Wakes up all blocked threads on this condvar.
@@ -197,7 +196,6 @@
 
     #[cold]
     fn notify_all_slow(&self, mutex: *mut RawMutex) -> usize {
-        unsafe {
             // Unpark one thread and requeue the rest onto the mutex
             let from = self as *const _ as usize;
             let to = mutex as usize;
@@ -221,7 +219,7 @@
                 // locking the queue. There is the possibility of a race if the
                 // mutex gets locked after we check, but that doesn't matter in
                 // this case.
-                if (*mutex).mark_parked_if_locked() {
+                if unsafe { (*mutex).mark_parked_if_locked() } {
                     RequeueOp::RequeueAll
                 } else {
                     RequeueOp::UnparkOneRequeueRest
@@ -231,14 +229,13 @@
                 // If we requeued threads to the mutex, mark it as having
                 // parked threads. The RequeueAll case is already handled above.
                 if op == RequeueOp::UnparkOneRequeueRest && result.requeued_threads != 0 {
-                    (*mutex).mark_parked();
+                    unsafe { (*mutex).mark_parked() };
                 }
                 TOKEN_NORMAL
             };
-            let res = parking_lot_core::unpark_requeue(from, to, validate, callback);
+            let res = unsafe { parking_lot_core::unpark_requeue(from, to, validate, callback) };
 
             res.unparked_threads + res.requeued_threads
-        }
     }
 
     /// Blocks the current thread until this condition variable receives a
@@ -297,7 +294,6 @@
     // This is a non-generic function to reduce the monomorphization cost of
     // using `wait_until`.
     fn wait_until_internal(&self, mutex: &RawMutex, timeout: Option<Instant>) -> WaitTimeoutResult {
-        unsafe {
             let result;
             let mut bad_mutex = false;
             let mut requeued = false;
@@ -319,7 +315,7 @@
                 };
                 let before_sleep = || {
                     // Unlock the mutex before sleeping...
-                    mutex.unlock();
+                    unsafe { mutex.unlock() };
                 };
                 let timed_out = |k, was_last_thread| {
                     // If we were requeued to a mutex, then we did not time out.
@@ -334,14 +330,14 @@
                         self.state.store(ptr::null_mut(), Ordering::Relaxed);
                     }
                 };
-                result = parking_lot_core::park(
+                result = unsafe { parking_lot_core::park(
                     addr,
                     validate,
                     before_sleep,
                     timed_out,
                     DEFAULT_PARK_TOKEN,
                     timeout,
-                );
+                ) };
             }
 
             // Panic if we tried to use multiple mutexes with a Condvar. Note
@@ -353,13 +349,12 @@
 
             // ... and re-lock it once we are done sleeping
             if result == ParkResult::Unparked(TOKEN_HANDOFF) {
-                deadlock::acquire_resource(mutex as *const _ as usize);
+                unsafe { deadlock::acquire_resource(mutex as *const _ as usize) };
             } else {
                 mutex.lock();
             }
 
             WaitTimeoutResult(!(result.is_unparked() || requeued))
-        }
     }
 
     /// Waits on this condition variable for a notification, timing out after a
@@ -389,6 +384,127 @@
         let deadline = util::to_deadline(timeout);
         self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, deadline)
     }
+
+    #[inline]
+    fn wait_while_until_internal<T, F>(
+        &self,
+        mutex_guard: &mut MutexGuard<'_, T>,
+        mut condition: F,
+        timeout: Option<Instant>,
+    ) -> WaitTimeoutResult
+    where
+        T: ?Sized,
+        F: FnMut(&mut T) -> bool,
+    {
+        let mut result = WaitTimeoutResult(false);
+
+        while !result.timed_out() && condition(mutex_guard.deref_mut()) {
+            result =
+                self.wait_until_internal(unsafe { MutexGuard::mutex(mutex_guard).raw() }, timeout);
+        }
+
+        result
+    }
+    /// Blocks the current thread until this condition variable receives a
+    /// notification. If the provided condition evaluates to `false`, then the
+    /// thread is no longer blocked and the operation is completed. If the
+    /// condition evaluates to `true`, then the thread is blocked again and
+    /// waits for another notification before repeating this process.
+    ///
+    /// This function will atomically unlock the mutex specified (represented by
+    /// `mutex_guard`) and block the current thread. This means that any calls
+    /// to `notify_*()` which happen logically after the mutex is unlocked are
+    /// candidates to wake this thread up. When this function call returns, the
+    /// lock specified will have been re-acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if another thread is waiting on the `Condvar`
+    /// with a different `Mutex` object.
+    #[inline]
+    pub fn wait_while<T, F>(&self, mutex_guard: &mut MutexGuard<'_, T>, condition: F)
+    where
+        T: ?Sized,
+        F: FnMut(&mut T) -> bool,
+    {
+        self.wait_while_until_internal(mutex_guard, condition, None);
+    }
+
+    /// Waits on this condition variable for a notification, timing out after
+    /// the specified time instant. If the provided condition evaluates to
+    /// `false`, then the thread is no longer blocked and the operation is
+    /// completed. If the condition evaluates to `true`, then the thread is
+    /// blocked again and waits for another notification before repeating
+    /// this process.
+    ///
+    /// The semantics of this function are equivalent to `wait()` except that
+    /// the thread will be blocked roughly until `timeout` is reached. This
+    /// method should not be used for precise timing due to anomalies such as
+    /// preemption or platform differences that may not cause the maximum
+    /// amount of time waited to be precisely `timeout`.
+    ///
+    /// Note that the best effort is made to ensure that the time waited is
+    /// measured with a monotonic clock, and not affected by the changes made to
+    /// the system time.
+    ///
+    /// The returned `WaitTimeoutResult` value indicates if the timeout is
+    /// known to have elapsed.
+    ///
+    /// Like `wait`, the lock specified will be re-acquired when this function
+    /// returns, regardless of whether the timeout elapsed or not.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if another thread is waiting on the `Condvar`
+    /// with a different `Mutex` object.
+    #[inline]
+    pub fn wait_while_until<T, F>(
+        &self,
+        mutex_guard: &mut MutexGuard<'_, T>,
+        condition: F,
+        timeout: Instant,
+    ) -> WaitTimeoutResult
+    where
+        T: ?Sized,
+        F: FnMut(&mut T) -> bool,
+    {
+        self.wait_while_until_internal(mutex_guard, condition, Some(timeout))
+    }
+
+    /// Waits on this condition variable for a notification, timing out after a
+    /// specified duration. If the provided condition evaluates to `false`,
+    /// then the thread is no longer blocked and the operation is completed.
+    /// If the condition evaluates to `true`, then the thread is blocked again
+    /// and waits for another notification before repeating this process.
+    ///
+    /// The semantics of this function are equivalent to `wait()` except that
+    /// the thread will be blocked for roughly no longer than `timeout`. This
+    /// method should not be used for precise timing due to anomalies such as
+    /// preemption or platform differences that may not cause the maximum
+    /// amount of time waited to be precisely `timeout`.
+    ///
+    /// Note that the best effort is made to ensure that the time waited is
+    /// measured with a monotonic clock, and not affected by the changes made to
+    /// the system time.
+    ///
+    /// The returned `WaitTimeoutResult` value indicates if the timeout is
+    /// known to have elapsed.
+    ///
+    /// Like `wait`, the lock specified will be re-acquired when this function
+    /// returns, regardless of whether the timeout elapsed or not.
+    #[inline]
+    pub fn wait_while_for<T: ?Sized, F>(
+        &self,
+        mutex_guard: &mut MutexGuard<'_, T>,
+        condition: F,
+        timeout: Duration,
+    ) -> WaitTimeoutResult
+    where
+        F: FnMut(&mut T) -> bool,
+    {
+        let deadline = util::to_deadline(timeout);
+        self.wait_while_until_internal(mutex_guard, condition, deadline)
+    }
 }
 
 impl Default for Condvar {
@@ -410,6 +526,8 @@
     use std::sync::mpsc::channel;
     use std::sync::Arc;
     use std::thread;
+    use std::thread::sleep;
+    use std::thread::JoinHandle;
     use std::time::Duration;
     use std::time::Instant;
 
@@ -578,6 +696,116 @@
         drop(g);
     }
 
+    fn spawn_wait_while_notifier(
+        mutex: Arc<Mutex<u32>>,
+        cv: Arc<Condvar>,
+        num_iters: u32,
+        timeout: Option<Instant>,
+    ) -> JoinHandle<()> {
+        thread::spawn(move || {
+            for epoch in 1..=num_iters {
+                // spin to wait for main test thread to block
+                // before notifying it to wake back up and check
+                // its condition.
+                let mut sleep_backoff = Duration::from_millis(1);
+                let _mutex_guard = loop {
+                    let mutex_guard = mutex.lock();
+
+                    if let Some(timeout) = timeout {
+                        if Instant::now() >= timeout {
+                            return;
+                        }
+                    }
+
+                    if *mutex_guard == epoch {
+                        break mutex_guard;
+                    }
+
+                    drop(mutex_guard);
+
+                    // give main test thread a good chance to
+                    // acquire the lock before this thread does.
+                    sleep(sleep_backoff);
+                    sleep_backoff *= 2;
+                };
+
+                cv.notify_one();
+            }
+        })
+    }
+
+    #[test]
+    fn wait_while_until_internal_does_not_wait_if_initially_false() {
+        let mutex = Arc::new(Mutex::new(0));
+        let cv = Arc::new(Condvar::new());
+
+        let condition = |counter: &mut u32| {
+            *counter += 1;
+            false
+        };
+
+        let mut mutex_guard = mutex.lock();
+        let timeout_result = cv
+            .wait_while_until_internal(&mut mutex_guard, condition, None);
+
+        assert!(!timeout_result.timed_out());
+        assert!(*mutex_guard == 1);
+    }
+
+    #[test]
+    fn wait_while_until_internal_times_out_before_false() {
+        let mutex = Arc::new(Mutex::new(0));
+        let cv = Arc::new(Condvar::new());
+
+        let num_iters = 3;
+        let condition = |counter: &mut u32| {
+            *counter += 1;
+            true
+        };
+
+        let mut mutex_guard = mutex.lock();
+        let timeout = Some(Instant::now() + Duration::from_millis(500));
+        let handle = spawn_wait_while_notifier(mutex.clone(), cv.clone(), num_iters, timeout);
+
+        let timeout_result =
+            cv.wait_while_until_internal(&mut mutex_guard, condition, timeout);
+
+        assert!(timeout_result.timed_out());
+        assert!(*mutex_guard == num_iters + 1);
+
+        // prevent deadlock with notifier
+        drop(mutex_guard);
+        handle.join().unwrap();
+    }
+
+    #[test]
+    fn wait_while_until_internal() {
+        let mutex = Arc::new(Mutex::new(0));
+        let cv = Arc::new(Condvar::new());
+
+        let num_iters = 4;
+
+        let condition = |counter: &mut u32| {
+            *counter += 1;
+            *counter <= num_iters
+        };
+
+        let mut mutex_guard = mutex.lock();
+        let handle = spawn_wait_while_notifier(mutex.clone(), cv.clone(), num_iters, None);
+
+        let timeout_result =
+            cv.wait_while_until_internal(&mut mutex_guard, condition, None);
+
+        assert!(!timeout_result.timed_out());
+        assert!(*mutex_guard == num_iters + 1);
+
+        let timeout_result = cv.wait_while_until_internal(&mut mutex_guard, condition, None);
+        handle.join().unwrap();
+
+        assert!(!timeout_result.timed_out());
+        assert!(*mutex_guard == num_iters + 2);
+    }
+
     #[test]
     #[should_panic]
     fn two_mutexes() {
diff --git a/src/fair_mutex.rs b/src/fair_mutex.rs
index 3e4c163..d7d7a77 100644
--- a/src/fair_mutex.rs
+++ b/src/fair_mutex.rs
@@ -35,7 +35,7 @@
 /// - No poisoning, the lock is released normally on panic.
 /// - Only requires 1 byte of space, whereas the standard library boxes the
 ///   `FairMutex` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
 /// - Does not require any drop glue when dropped.
 /// - Inline fast path for the uncontended case.
 /// - Efficient handling of micro-contention using adaptive spinning.
diff --git a/src/mutex.rs b/src/mutex.rs
index 71bc351..f3f8aa9 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -42,7 +42,7 @@
 /// - No poisoning, the lock is released normally on panic.
 /// - Only requires 1 byte of space, whereas the standard library boxes the
 ///   `Mutex` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
 /// - Does not require any drop glue when dropped.
 /// - Inline fast path for the uncontended case.
 /// - Efficient handling of micro-contention using adaptive spinning.
diff --git a/src/once.rs b/src/once.rs
index f458c9c..6b91ac4 100644
--- a/src/once.rs
+++ b/src/once.rs
@@ -258,11 +258,11 @@
 
             // Park our thread until we are woken up by the thread that owns the
             // lock.
+            let addr = self as *const _ as usize;
+            let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT;
+            let before_sleep = || {};
+            let timed_out = |_, _| unreachable!();
             unsafe {
-                let addr = self as *const _ as usize;
-                let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT;
-                let before_sleep = || {};
-                let timed_out = |_, _| unreachable!();
                 parking_lot_core::park(
                     addr,
                     validate,
@@ -285,8 +285,8 @@
                 let once = self.0;
                 let state = once.0.swap(POISON_BIT, Ordering::Release);
                 if state & PARKED_BIT != 0 {
+                    let addr = once as *const _ as usize;
                     unsafe {
-                        let addr = once as *const _ as usize;
                         parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
                     }
                 }
@@ -307,8 +307,8 @@
         // Now unlock the state, set the done bit and unpark all threads
         let state = self.0.swap(DONE_BIT, Ordering::Release);
         if state & PARKED_BIT != 0 {
+            let addr = self as *const _ as usize;
             unsafe {
-                let addr = self as *const _ as usize;
                 parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
             }
         }
diff --git a/src/raw_rwlock.rs b/src/raw_rwlock.rs
index 21d338b..6d1fef9 100644
--- a/src/raw_rwlock.rs
+++ b/src/raw_rwlock.rs
@@ -988,8 +988,8 @@
                 if let Err(x) = self.state.compare_exchange_weak(
                     state,
                     state | WRITER_PARKED_BIT,
-                    Ordering::Relaxed,
-                    Ordering::Relaxed,
+                    Ordering::Acquire,
+                    Ordering::Acquire,
                 ) {
                     state = x;
                     continue;
diff --git a/src/rwlock.rs b/src/rwlock.rs
index 512114c..4167a85 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -55,7 +55,7 @@
 /// - No poisoning, the lock is released normally on panic.
 /// - Only requires 1 word of space, whereas the standard library boxes the
 ///   `RwLock` due to platform limitations.
-/// - Can be statically constructed (requires the `const_fn` nightly feature).
+/// - Can be statically constructed.
 /// - Does not require any drop glue when dropped.
 /// - Inline fast path for the uncontended case.
 /// - Efficient handling of micro-contention using adaptive spinning.