Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
232
third-party/vendor/parking_lot/src/deadlock.rs
vendored
Normal file
232
third-party/vendor/parking_lot/src/deadlock.rs
vendored
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
//! \[Experimental\] Deadlock detection
|
||||
//!
|
||||
//! This feature is optional and can be enabled via the `deadlock_detection` feature flag.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! #[cfg(feature = "deadlock_detection")]
|
||||
//! { // only for #[cfg]
|
||||
//! use std::thread;
|
||||
//! use std::time::Duration;
|
||||
//! use parking_lot::deadlock;
|
||||
//!
|
||||
//! // Create a background thread which checks for deadlocks every 10s
|
||||
//! thread::spawn(move || {
|
||||
//! loop {
|
||||
//! thread::sleep(Duration::from_secs(10));
|
||||
//! let deadlocks = deadlock::check_deadlock();
|
||||
//! if deadlocks.is_empty() {
|
||||
//! continue;
|
||||
//! }
|
||||
//!
|
||||
//! println!("{} deadlocks detected", deadlocks.len());
|
||||
//! for (i, threads) in deadlocks.iter().enumerate() {
|
||||
//! println!("Deadlock #{}", i);
|
||||
//! for t in threads {
|
||||
//! println!("Thread Id {:#?}", t.thread_id());
|
||||
//! println!("{:#?}", t.backtrace());
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! });
|
||||
//! } // only for #[cfg]
|
||||
//! ```
|
||||
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
pub use parking_lot_core::deadlock::check_deadlock;
|
||||
pub(crate) use parking_lot_core::deadlock::{acquire_resource, release_resource};
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
mod tests {
|
||||
use crate::{Mutex, ReentrantMutex, RwLock};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread::{self, sleep};
|
||||
use std::time::Duration;
|
||||
|
||||
// We need to serialize these tests since deadlock detection uses global state
|
||||
static DEADLOCK_DETECTION_LOCK: Mutex<()> = crate::const_mutex(());
|
||||
|
||||
fn check_deadlock() -> bool {
|
||||
use parking_lot_core::deadlock::check_deadlock;
|
||||
!check_deadlock().is_empty()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mutex_deadlock() {
|
||||
let _guard = DEADLOCK_DETECTION_LOCK.lock();
|
||||
|
||||
let m1: Arc<Mutex<()>> = Default::default();
|
||||
let m2: Arc<Mutex<()>> = Default::default();
|
||||
let m3: Arc<Mutex<()>> = Default::default();
|
||||
let b = Arc::new(Barrier::new(4));
|
||||
|
||||
let m1_ = m1.clone();
|
||||
let m2_ = m2.clone();
|
||||
let m3_ = m3.clone();
|
||||
let b1 = b.clone();
|
||||
let b2 = b.clone();
|
||||
let b3 = b.clone();
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
let _t1 = thread::spawn(move || {
|
||||
let _g = m1.lock();
|
||||
b1.wait();
|
||||
let _ = m2_.lock();
|
||||
});
|
||||
|
||||
let _t2 = thread::spawn(move || {
|
||||
let _g = m2.lock();
|
||||
b2.wait();
|
||||
let _ = m3_.lock();
|
||||
});
|
||||
|
||||
let _t3 = thread::spawn(move || {
|
||||
let _g = m3.lock();
|
||||
b3.wait();
|
||||
let _ = m1_.lock();
|
||||
});
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
b.wait();
|
||||
sleep(Duration::from_millis(50));
|
||||
assert!(check_deadlock());
|
||||
|
||||
assert!(!check_deadlock());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mutex_deadlock_reentrant() {
|
||||
let _guard = DEADLOCK_DETECTION_LOCK.lock();
|
||||
|
||||
let m1: Arc<Mutex<()>> = Default::default();
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
let _t1 = thread::spawn(move || {
|
||||
let _g = m1.lock();
|
||||
let _ = m1.lock();
|
||||
});
|
||||
|
||||
sleep(Duration::from_millis(50));
|
||||
assert!(check_deadlock());
|
||||
|
||||
assert!(!check_deadlock());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remutex_deadlock() {
|
||||
let _guard = DEADLOCK_DETECTION_LOCK.lock();
|
||||
|
||||
let m1: Arc<ReentrantMutex<()>> = Default::default();
|
||||
let m2: Arc<ReentrantMutex<()>> = Default::default();
|
||||
let m3: Arc<ReentrantMutex<()>> = Default::default();
|
||||
let b = Arc::new(Barrier::new(4));
|
||||
|
||||
let m1_ = m1.clone();
|
||||
let m2_ = m2.clone();
|
||||
let m3_ = m3.clone();
|
||||
let b1 = b.clone();
|
||||
let b2 = b.clone();
|
||||
let b3 = b.clone();
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
let _t1 = thread::spawn(move || {
|
||||
let _g = m1.lock();
|
||||
let _g = m1.lock();
|
||||
b1.wait();
|
||||
let _ = m2_.lock();
|
||||
});
|
||||
|
||||
let _t2 = thread::spawn(move || {
|
||||
let _g = m2.lock();
|
||||
let _g = m2.lock();
|
||||
b2.wait();
|
||||
let _ = m3_.lock();
|
||||
});
|
||||
|
||||
let _t3 = thread::spawn(move || {
|
||||
let _g = m3.lock();
|
||||
let _g = m3.lock();
|
||||
b3.wait();
|
||||
let _ = m1_.lock();
|
||||
});
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
b.wait();
|
||||
sleep(Duration::from_millis(50));
|
||||
assert!(check_deadlock());
|
||||
|
||||
assert!(!check_deadlock());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rwlock_deadlock() {
|
||||
let _guard = DEADLOCK_DETECTION_LOCK.lock();
|
||||
|
||||
let m1: Arc<RwLock<()>> = Default::default();
|
||||
let m2: Arc<RwLock<()>> = Default::default();
|
||||
let m3: Arc<RwLock<()>> = Default::default();
|
||||
let b = Arc::new(Barrier::new(4));
|
||||
|
||||
let m1_ = m1.clone();
|
||||
let m2_ = m2.clone();
|
||||
let m3_ = m3.clone();
|
||||
let b1 = b.clone();
|
||||
let b2 = b.clone();
|
||||
let b3 = b.clone();
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
let _t1 = thread::spawn(move || {
|
||||
let _g = m1.read();
|
||||
b1.wait();
|
||||
let _g = m2_.write();
|
||||
});
|
||||
|
||||
let _t2 = thread::spawn(move || {
|
||||
let _g = m2.read();
|
||||
b2.wait();
|
||||
let _g = m3_.write();
|
||||
});
|
||||
|
||||
let _t3 = thread::spawn(move || {
|
||||
let _g = m3.read();
|
||||
b3.wait();
|
||||
let _ = m1_.write();
|
||||
});
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
b.wait();
|
||||
sleep(Duration::from_millis(50));
|
||||
assert!(check_deadlock());
|
||||
|
||||
assert!(!check_deadlock());
|
||||
}
|
||||
|
||||
#[cfg(rwlock_deadlock_detection_not_supported)]
|
||||
#[test]
|
||||
fn test_rwlock_deadlock_reentrant() {
|
||||
let _guard = DEADLOCK_DETECTION_LOCK.lock();
|
||||
|
||||
let m1: Arc<RwLock<()>> = Default::default();
|
||||
|
||||
assert!(!check_deadlock());
|
||||
|
||||
let _t1 = thread::spawn(move || {
|
||||
let _g = m1.read();
|
||||
let _ = m1.write();
|
||||
});
|
||||
|
||||
sleep(Duration::from_millis(50));
|
||||
assert!(check_deadlock());
|
||||
|
||||
assert!(!check_deadlock());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue