Snap for 8564071 from af21f75d839f575817afcae347699b4515f528e1 to mainline-conscrypt-release

Change-Id: Ie884593e70a626c99a81ea75662fb5f8f1a4e7a7
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index e1a0b04..38c6551 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "86969fd7baf94312520e0b5a5f3b0861a0fd411b"
-  }
-}
+    "sha1": "a75875b0bf904287a9749e8eabea919b5e9dd8a9"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index d613089..4d33593 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -2,11 +2,11 @@
 
 on:
   push:
-    branches-ignore:
-      - trying.tmp
-      - staging.tmp
+    branches:
+      - trying
+      - staging
   pull_request:
-    
+
 env:
   RUST_TEST_THREADS: 1
 
@@ -16,15 +16,18 @@
     strategy:
       matrix:
         os: [ubuntu, macos, windows]
-        channel: [1.36.0, stable, beta, nightly]
-        feature: [serde, deadlock_detection]
+        channel: [1.49.0, stable, beta, nightly]
+        feature: [arc_lock, serde, deadlock_detection]
         exclude: 
           - feature: deadlock_detection
-            channel: '1.36.0'
+            channel: '1.49.0'
         include:
           - channel: nightly
             feature: nightly
             os: ubuntu
+          - channel: nightly
+            feature: hardware-lock-elision
+            os: ubuntu
 
     steps:
     - uses: actions/checkout@v2
@@ -53,7 +56,7 @@
     steps:
       - uses: actions/checkout@v2
       - run: rustup default nightly
-      - run: cargo doc --workspace --features serde,deadlock_detection --no-deps -p parking_lot -p parking_lot_core -p lock_api
+      - run: cargo doc --workspace --features arc_lock,serde,deadlock_detection --no-deps -p parking_lot -p parking_lot_core -p lock_api
   benchmark:
     runs-on: ubuntu-latest
     steps:
diff --git a/Android.bp b/Android.bp
index 731530a..17f0e2b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
-// This file is generated by cargo2android.py --run --device --dependencies.
+// This file is generated by cargo2android.py --config cargo2android.json.
+// Do not modify this file as changes will be overridden on upgrade.
 
 package {
     default_applicable_licenses: ["external_rust_crates_parking_lot_license"],
@@ -40,22 +41,19 @@
     name: "libparking_lot",
     host_supported: true,
     crate_name: "parking_lot",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.12.0",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: ["default"],
     rustlibs: [
-        "libinstant",
         "liblock_api",
         "libparking_lot_core",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.bluetooth",
+        "com.android.virt",
+    ],
+    min_sdk_version: "29",
 }
-
-// dependent_library ["feature_list"]
-//   cfg-if-0.1.10
-//   cfg-if-1.0.0
-//   instant-0.1.8
-//   libc-0.2.80 "default,std"
-//   lock_api-0.4.2
-//   parking_lot_core-0.8.0
-//   scopeguard-1.1.0
-//   smallvec-1.5.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a473463..d1951e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,41 @@
+## 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.
+- Disabled eventual fairness on wasm32-unknown-unknown. (#302)
+- Added a rwlock method to report if lock is held exclusively. (#303)
+- Use new `asm!` macro. (#304)
+- Use windows-rs instead of winapi for faster builds. (#311)
+- Moved hardware lock elision support to a separate Cargo feature. (#313)
+- Removed used of deprecated `spin_loop_hint`. (#314)
+
+## parking_lot 0.11.2, parking_lot_core 0.8.4, lock_api 0.4.5 (2021-08-28)
+
+- Fixed incorrect memory orderings on `RwLock` and `WordLock`. (#294, #292)
+- Added `Arc`-based lock guards. (#291)
+- Added workaround for TSan's lack of support for `fence`. (#292)
+
+## lock_api 0.4.4 (2021-05-01)
+
+- Update for latest nightly. (#281)
+
+## lock_api 0.4.3 (2021-04-03)
+
+- Added `[Raw]ReentrantMutex::is_owned`. (#280)
+
+## parking_lot_core 0.8.3 (2021-02-12)
+
+- Updated smallvec to 1.6. (#276)
+
+## parking_lot_core 0.8.2 (2020-12-21)
+
+- Fixed assertion failure on OpenBSD. (#270)
+
+## parking_lot_core 0.8.1 (2020-12-04)
+
+- Removed deprecated CloudABI support. (#263)
+- Fixed build on wasm32-unknown-unknown. (#265)
+- Relaxed dependency on `smallvec`. (#266)
+
 ## parking_lot 0.11.1, lock_api 0.4.2 (2020-11-18)
 
 - Fix bounds on Send and Sync impls for lock guards. (#262)
diff --git a/Cargo.toml b/Cargo.toml
index c78888f..6f58afa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
 name = "parking_lot"
-version = "0.11.1"
+version = "0.12.0"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 description = "More compact and efficient implementations of the standard synchronization primitives."
 readme = "README.md"
@@ -21,26 +20,23 @@
 categories = ["concurrency"]
 license = "Apache-2.0/MIT"
 repository = "https://github.com/Amanieu/parking_lot"
-[dependencies.instant]
-version = "0.1.4"
-
 [dependencies.lock_api]
-version = "0.4.0"
+version = "0.4.6"
 
 [dependencies.parking_lot_core]
-version = "0.8.0"
+version = "0.9.0"
 [dev-dependencies.bincode]
-version = "1.3.0"
+version = "1.3.3"
 
 [dev-dependencies.rand]
-version = "0.7.3"
+version = "0.8.3"
 
 [features]
+arc_lock = ["lock_api/arc_lock"]
 deadlock_detection = ["parking_lot_core/deadlock_detection"]
 default = []
+hardware-lock-elision = []
 nightly = ["parking_lot_core/nightly", "lock_api/nightly"]
 owning_ref = ["lock_api/owning_ref"]
 send_guard = []
 serde = ["lock_api/serde"]
-stdweb = ["instant/stdweb"]
-wasm-bindgen = ["instant/wasm-bindgen"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 67a2555..bb501be 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "parking_lot"
-version = "0.11.1"
+version = "0.12.0"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 description = "More compact and efficient implementations of the standard synchronization primitives."
 license = "Apache-2.0/MIT"
@@ -11,25 +11,24 @@
 edition = "2018"
 
 [dependencies]
-parking_lot_core = { path = "core", version = "0.8.0" }
-lock_api = { path = "lock_api", version = "0.4.0" }
-instant = "0.1.4"
+parking_lot_core = { path = "core", version = "0.9.0" }
+lock_api = { path = "lock_api", version = "0.4.6" }
 
 [dev-dependencies]
-rand = "0.7.3"
+rand = "0.8.3"
 
 # Used when testing out serde support.
-bincode = "1.3.0"
+bincode = "1.3.3"
 
 [features]
 default = []
+arc_lock = ["lock_api/arc_lock"]
 owning_ref = ["lock_api/owning_ref"]
 nightly = ["parking_lot_core/nightly", "lock_api/nightly"]
 deadlock_detection = ["parking_lot_core/deadlock_detection"]
 serde = ["lock_api/serde"]
-stdweb = ["instant/stdweb"]
-wasm-bindgen = ["instant/wasm-bindgen"]
 send_guard = []
+hardware-lock-elision = []
 
 [workspace]
 exclude = ["benchmark"]
diff --git a/METADATA b/METADATA
index d750618..10f98ed 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/parking_lot/parking_lot-0.11.1.crate"
+    value: "https://static.crates.io/crates/parking_lot/parking_lot-0.12.0.crate"
   }
-  version: "0.11.1"
+  version: "0.12.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
-    month: 11
-    day: 17
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/README.md b/README.md
index d3e5b0b..5bda8d8 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,7 @@
    library versions of those types.
 7. `RwLock` takes advantage of hardware lock elision on processors that
    support it, which can lead to huge performance wins with many readers.
+   This must be enabled with the `hardware-lock-elision` feature.
 8. `RwLock` uses a task-fair locking policy, which avoids reader and writer
    starvation, whereas the standard library version makes no guarantees.
 9. `Condvar` is guaranteed not to produce spurious wakeups. A thread will
@@ -93,8 +94,6 @@
 - 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.
-- `RwLock` will not be able to take advantage of hardware lock elision for
-  readers, which improves performance when there are multiple readers.
 - The `wasm32-unknown-unknown` target is only supported on nightly and requires
   `-C target-feature=+atomics` in `RUSTFLAGS`.
 
@@ -126,13 +125,17 @@
 Note that the `deadlock_detection` and `send_guard` features are incompatible
 and cannot be used together.
 
+Hardware lock elision support for x86 can be enabled with the
+`hardware-lock-elision` feature. This requires Rust 1.59 due to the use of
+inline assembly.
+
 The core parking lot API is provided by the `parking_lot_core` crate. It is
 separate from the synchronization primitives in the `parking_lot` crate so that
 changes to the core API do not cause breaking changes for users of `parking_lot`.
 
 ## Minimum Rust version
 
-The current minimum required Rust version is 1.36. Any change to this is
+The current minimum required Rust version is 1.49. Any change to this is
 considered a breaking change and will require a major version bump.
 
 ## License
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..f439cf8
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,8 @@
+// Generated by update_crate_tests.py for tests that depend on this crate.
+{
+  "imports": [
+    {
+      "path": "external/rust/crates/vulkano"
+    }
+  ]
+}
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..e48e3b8
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,10 @@
+{
+  "apex-available": [
+    "//apex_available:platform",
+    "com.android.bluetooth",
+    "com.android.virt"
+  ],
+  "device": true,
+  "min-sdk-version": "29",
+  "run": true
+}
diff --git a/src/condvar.rs b/src/condvar.rs
index 534b8af..9eaf300 100644
--- a/src/condvar.rs
+++ b/src/condvar.rs
@@ -12,10 +12,9 @@
     fmt, ptr,
     sync::atomic::{AtomicPtr, Ordering},
 };
-use instant::Instant;
 use lock_api::RawMutex as RawMutex_;
 use parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN};
-use std::time::Duration;
+use std::time::{Duration, Instant};
 
 /// A type indicating whether a timed wait on a condition variable returned
 /// due to a time out or not.
@@ -381,12 +380,6 @@
     ///
     /// Like `wait`, the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the given `timeout` is so large that it can't be added to the current time.
-    /// This panic is not possible if the crate is built with the `nightly` feature, then a too
-    /// large `timeout` becomes equivalent to just calling `wait`.
     #[inline]
     pub fn wait_for<T: ?Sized>(
         &self,
@@ -414,11 +407,11 @@
 #[cfg(test)]
 mod tests {
     use crate::{Condvar, Mutex, MutexGuard};
-    use instant::Instant;
     use std::sync::mpsc::channel;
     use std::sync::Arc;
     use std::thread;
     use std::time::Duration;
+    use std::time::Instant;
 
     #[test]
     fn smoke() {
@@ -557,14 +550,7 @@
             let _g = m2.lock();
             c2.notify_one();
         });
-        // Non-nightly panics on too large timeouts. Nightly treats it as indefinite wait.
-        let very_long_timeout = if cfg!(feature = "nightly") {
-            Duration::from_secs(u64::max_value())
-        } else {
-            Duration::from_millis(u32::max_value() as u64)
-        };
-
-        let timeout_res = c.wait_for(&mut g, very_long_timeout);
+        let timeout_res = c.wait_for(&mut g, Duration::from_secs(u64::max_value()));
         assert!(!timeout_res.timed_out());
 
         drop(g);
diff --git a/src/elision.rs b/src/elision.rs
index 68cfa63..8fa229e 100644
--- a/src/elision.rs
+++ b/src/elision.rs
@@ -5,6 +5,8 @@
 // http://opensource.org/licenses/MIT>, at your option. This file may not be
 // copied, modified, or distributed except according to those terms.
 
+#[cfg(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64")))]
+use std::arch::asm;
 use std::sync::atomic::AtomicUsize;
 
 // Extension trait to add lock elision primitives to atomic types
@@ -26,14 +28,14 @@
 #[inline]
 pub fn have_elision() -> bool {
     cfg!(all(
-        feature = "nightly",
+        feature = "hardware-lock-elision",
         any(target_arch = "x86", target_arch = "x86_64"),
     ))
 }
 
 // This implementation is never actually called because it is guarded by
 // have_elision().
-#[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))]
+#[cfg(not(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64"))))]
 impl AtomicElisionExt for AtomicUsize {
     type IntType = usize;
 
@@ -48,37 +50,33 @@
     }
 }
 
-#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))]
+#[cfg(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64")))]
 impl AtomicElisionExt for AtomicUsize {
     type IntType = usize;
 
-    #[cfg(target_pointer_width = "32")]
     #[inline]
     fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
         unsafe {
+            use core::arch::asm;
             let prev: usize;
-            llvm_asm!("xacquire; lock; cmpxchgl $2, $1"
-                      : "={eax}" (prev), "+*m" (self)
-                      : "r" (new), "{eax}" (current)
-                      : "memory"
-                      : "volatile");
-            if prev == current {
-                Ok(prev)
-            } else {
-                Err(prev)
-            }
-        }
-    }
-    #[cfg(target_pointer_width = "64")]
-    #[inline]
-    fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
-        unsafe {
-            let prev: usize;
-            llvm_asm!("xacquire; lock; cmpxchgq $2, $1"
-                      : "={rax}" (prev), "+*m" (self)
-                      : "r" (new), "{rax}" (current)
-                      : "memory"
-                      : "volatile");
+            #[cfg(target_pointer_width = "32")]
+            asm!(
+                "xacquire",
+                "lock",
+                "cmpxchg [{:e}], {:e}",
+                in(reg) self,
+                in(reg) new,
+                inout("eax") current => prev,
+            );
+            #[cfg(target_pointer_width = "64")]
+            asm!(
+                "xacquire",
+                "lock",
+                "cmpxchg [{}], {}",
+                in(reg) self,
+                in(reg) new,
+                inout("rax") current => prev,
+            );
             if prev == current {
                 Ok(prev)
             } else {
@@ -87,29 +85,27 @@
         }
     }
 
-    #[cfg(target_pointer_width = "32")]
     #[inline]
     fn elision_fetch_sub_release(&self, val: usize) -> usize {
         unsafe {
+            use core::arch::asm;
             let prev: usize;
-            llvm_asm!("xrelease; lock; xaddl $2, $1"
-                      : "=r" (prev), "+*m" (self)
-                      : "0" (val.wrapping_neg())
-                      : "memory"
-                      : "volatile");
-            prev
-        }
-    }
-    #[cfg(target_pointer_width = "64")]
-    #[inline]
-    fn elision_fetch_sub_release(&self, val: usize) -> usize {
-        unsafe {
-            let prev: usize;
-            llvm_asm!("xrelease; lock; xaddq $2, $1"
-                      : "=r" (prev), "+*m" (self)
-                      : "0" (val.wrapping_neg())
-                      : "memory"
-                      : "volatile");
+            #[cfg(target_pointer_width = "32")]
+            asm!(
+                "xrelease",
+                "lock",
+                "xadd [{:e}], {:e}",
+                in(reg) self,
+                inout(reg) val.wrapping_neg() => prev,
+            );
+            #[cfg(target_pointer_width = "64")]
+            asm!(
+                "xrelease",
+                "lock",
+                "xadd [{}], {}",
+                in(reg) self,
+                inout(reg) val.wrapping_neg() => prev,
+            );
             prev
         }
     }
diff --git a/src/fair_mutex.rs b/src/fair_mutex.rs
index 449c53b..3e4c163 100644
--- a/src/fair_mutex.rs
+++ b/src/fair_mutex.rs
@@ -11,24 +11,21 @@
 /// A mutual exclusive primitive that is always fair, useful for protecting shared data
 ///
 /// This mutex will block threads waiting for the lock to become available. The
-/// mutex can also be statically initialized or created via a `new`
+/// mutex can be statically initialized or created by the `new`
 /// constructor. Each mutex has a type parameter which represents the data that
 /// it is protecting. The data can only be accessed through the RAII guards
 /// returned from `lock` and `try_lock`, which guarantees that the data is only
 /// ever accessed when the mutex is locked.
 ///
-/// The regular mutex provided by `parking_lot` uses eventual locking fairness
+/// The regular mutex provided by `parking_lot` uses eventual fairness
 /// (after some time it will default to the fair algorithm), but eventual
-/// fairness does not provide the same garantees a always fair method would.
-/// Fair mutexes are generally slower, but sometimes needed. This wrapper was
-/// created to avoid using a unfair protocol when it's forbidden by mistake.
+/// fairness does not provide the same guarantees an always fair method would.
+/// Fair mutexes are generally slower, but sometimes needed.
 ///
-/// In a fair mutex the lock is provided to whichever thread asked first,
-/// they form a queue and always follow the first-in first-out order. This
-/// means some thread in the queue won't be able to steal the lock and use it fast
-/// to increase throughput, at the cost of latency. Since the response time will grow
-/// for some threads that are waiting for the lock and losing to faster but later ones,
-/// but it may make sending more responses possible.
+/// In a fair mutex the waiters form a queue, and the lock is always granted to
+/// the next requester in the queue, in first-in first-out order. This ensures
+/// that one thread cannot starve others by quickly re-acquiring the lock after
+/// releasing it.
 ///
 /// A fair mutex may not be interesting if threads have different priorities (this is known as
 /// priority inversion).
diff --git a/src/lib.rs b/src/lib.rs
index 7ff2c79..03639a6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,7 +11,6 @@
 
 #![warn(missing_docs)]
 #![warn(rust_2018_idioms)]
-#![cfg_attr(feature = "nightly", feature(llvm_asm))]
 
 mod condvar;
 mod elision;
diff --git a/src/mutex.rs b/src/mutex.rs
index 9f63cb9..71bc351 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -11,7 +11,7 @@
 /// A mutual exclusion primitive useful for protecting shared data
 ///
 /// This mutex will block threads waiting for the lock to become available. The
-/// mutex can also be statically initialized or created via a `new`
+/// mutex can be statically initialized or created by the `new`
 /// constructor. Each mutex has a type parameter which represents the data that
 /// it is protecting. The data can only be accessed through the RAII guards
 /// returned from `lock` and `try_lock`, which guarantees that the data is only
diff --git a/src/raw_mutex.rs b/src/raw_mutex.rs
index 06667d3..b1ae7ee 100644
--- a/src/raw_mutex.rs
+++ b/src/raw_mutex.rs
@@ -10,9 +10,9 @@
     sync::atomic::{AtomicU8, Ordering},
     time::Duration,
 };
-use instant::Instant;
 use lock_api::RawMutex as RawMutex_;
 use parking_lot_core::{self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN};
+use std::time::Instant;
 
 // UnparkToken used to indicate that that the target thread should attempt to
 // lock the mutex again as soon as it is unparked.
diff --git a/src/raw_rwlock.rs b/src/raw_rwlock.rs
index 75a9812..21d338b 100644
--- a/src/raw_rwlock.rs
+++ b/src/raw_rwlock.rs
@@ -12,12 +12,11 @@
     cell::Cell,
     sync::atomic::{AtomicUsize, Ordering},
 };
-use instant::Instant;
 use lock_api::{RawRwLock as RawRwLock_, RawRwLockUpgrade};
 use parking_lot_core::{
     self, deadlock, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult, UnparkToken,
 };
-use std::time::Duration;
+use std::time::{Duration, Instant};
 
 // This reader-writer lock implementation is based on Boost's upgrade_mutex:
 // https://github.com/boostorg/thread/blob/fc08c1fe2840baeeee143440fba31ef9e9a813c8/include/boost/thread/v2/shared_mutex.hpp#L432
@@ -144,6 +143,12 @@
         let state = self.state.load(Ordering::Relaxed);
         state & (WRITER_BIT | READERS_MASK) != 0
     }
+
+    #[inline]
+    fn is_locked_exclusive(&self) -> bool {
+        let state = self.state.load(Ordering::Relaxed);
+        state & (WRITER_BIT) != 0
+    }
 }
 
 unsafe impl lock_api::RawRwLockFair for RawRwLock {
@@ -362,7 +367,7 @@
     unsafe fn upgrade(&self) {
         let state = self.state.fetch_sub(
             (ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
-            Ordering::Relaxed,
+            Ordering::Acquire,
         );
         if state & READERS_MASK != ONE_READER {
             let result = self.upgrade_slow(None);
@@ -377,7 +382,7 @@
             .compare_exchange_weak(
                 ONE_READER | UPGRADABLE_BIT,
                 WRITER_BIT,
-                Ordering::Relaxed,
+                Ordering::Acquire,
                 Ordering::Relaxed,
             )
             .is_ok()
diff --git a/src/rwlock.rs b/src/rwlock.rs
index 70e1b1a..512114c 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -408,6 +408,8 @@
                 write_result.is_none(),
                 "try_write should fail while read_guard is in scope"
             );
+            assert!(lock.is_locked());
+            assert!(!lock.is_locked_exclusive());
 
             drop(read_guard);
         }
@@ -419,6 +421,8 @@
                 write_result.is_none(),
                 "try_write should fail while upgrade_guard is in scope"
             );
+            assert!(lock.is_locked());
+            assert!(!lock.is_locked_exclusive());
 
             drop(upgrade_guard);
         }
@@ -430,6 +434,8 @@
                 write_result.is_none(),
                 "try_write should fail while write_guard is in scope"
             );
+            assert!(lock.is_locked());
+            assert!(lock.is_locked_exclusive());
 
             drop(write_guard);
         }
@@ -615,4 +621,22 @@
         .join()
         .unwrap();
     }
+
+    #[test]
+    fn test_rw_write_is_locked() {
+        let lock = RwLock::new(0isize);
+        {
+            let _read_guard = lock.read();
+
+            assert!(lock.is_locked());
+            assert!(!lock.is_locked_exclusive());
+        }
+
+        {
+            let _write_guard = lock.write();
+
+            assert!(lock.is_locked());
+            assert!(lock.is_locked_exclusive());
+        }
+    }
 }
diff --git a/src/util.rs b/src/util.rs
index 19cc2c2..c5496fc 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -5,8 +5,7 @@
 // http://opensource.org/licenses/MIT>, at your option. This file may not be
 // copied, modified, or distributed except according to those terms.
 
-use instant::Instant;
-use std::time::Duration;
+use std::time::{Duration, Instant};
 
 // Option::unchecked_unwrap
 pub trait UncheckedOptionExt<T> {