1#[cfg(feature = "deadlock_detection")]
43pub use parking_lot_core::deadlock::check_deadlock;
44
45#[inline]
51pub(crate) unsafe fn acquire_resource(key: usize) {
52 if falsecfg!(feature = "deadlock_detection") {
53 unsafe {
54 parking_lot_core::deadlock::acquire_resource(key);
55 }
56 }
57}
58#[inline]
59pub(crate) unsafe fn release_resource(key: usize) {
60 if falsecfg!(feature = "deadlock_detection") {
61 unsafe {
62 parking_lot_core::deadlock::release_resource(key);
63 }
64 }
65}
66
67#[cfg(test)]
68#[cfg(feature = "deadlock_detection")]
69mod tests {
70 use crate::{Mutex, Once, ReentrantMutex, RwLock};
71 use std::sync::{Arc, Barrier, mpsc};
72 use std::thread::{self, sleep};
73 use std::time::Duration;
74
75 static DEADLOCK_DETECTION_LOCK: Mutex<()> = Mutex::new(());
78
79 fn check_deadlock() -> bool {
80 use parking_lot_core::deadlock::check_deadlock;
81 !check_deadlock().is_empty()
82 }
83
84 #[track_caller]
85 fn assert_deadlock(thread_count: usize) {
86 let deadlocks = parking_lot_core::deadlock::check_deadlock();
87 assert_eq!(deadlocks.len(), 1);
88 assert_eq!(deadlocks[0].len(), thread_count);
89 }
90
91 #[test]
92 fn test_mutex_deadlock() {
93 let _guard = DEADLOCK_DETECTION_LOCK.lock();
94
95 let m1: Arc<Mutex<()>> = Default::default();
96 let m2: Arc<Mutex<()>> = Default::default();
97 let m3: Arc<Mutex<()>> = Default::default();
98 let b = Arc::new(Barrier::new(4));
99
100 let m1_ = m1.clone();
101 let m2_ = m2.clone();
102 let m3_ = m3.clone();
103 let b1 = b.clone();
104 let b2 = b.clone();
105 let b3 = b.clone();
106
107 assert!(!check_deadlock());
108
109 let _t1 = thread::spawn(move || {
110 let _g = m1.lock();
111 b1.wait();
112 let _blocked = m2_.lock();
113 });
114
115 let _t2 = thread::spawn(move || {
116 let _g = m2.lock();
117 b2.wait();
118 let _blocked = m3_.lock();
119 });
120
121 let _t3 = thread::spawn(move || {
122 let _g = m3.lock();
123 b3.wait();
124 let _blocked = m1_.lock();
125 });
126
127 assert!(!check_deadlock());
128
129 b.wait();
130 sleep(Duration::from_millis(50));
131 assert_deadlock(3);
132
133 assert!(!check_deadlock());
134 }
135
136 #[test]
137 fn test_mutex_deadlock_reentrant() {
138 let _guard = DEADLOCK_DETECTION_LOCK.lock();
139
140 let m1: Arc<Mutex<()>> = Default::default();
141
142 assert!(!check_deadlock());
143
144 let _t1 = thread::spawn(move || {
145 let _g = m1.lock();
146 let _blocked = m1.lock();
147 });
148
149 sleep(Duration::from_millis(50));
150 assert_deadlock(1);
151
152 assert!(!check_deadlock());
153 }
154
155 #[test]
156 fn test_once_deadlock() {
157 let _guard = DEADLOCK_DETECTION_LOCK.lock();
158
159 let once = Arc::new(Once::new());
160 let mutex = Arc::new(Mutex::new(()));
161 let barrier = Arc::new(Barrier::new(2));
162
163 let once1 = Arc::clone(&once);
164 let mutex1 = Arc::clone(&mutex);
165 let barrier1 = Arc::clone(&barrier);
166 let _t1 = thread::spawn(move || {
167 once1.call_once(|| {
168 barrier1.wait();
169 let _blocked = mutex1.lock();
170 });
171 });
172
173 let barrier2 = Arc::clone(&barrier);
174 let _t2 = thread::spawn(move || {
175 let _guard = mutex.lock();
176 barrier2.wait();
177 once.call_once(|| unreachable!());
178 });
179
180 sleep(Duration::from_millis(50));
181 assert_deadlock(2);
182 assert!(!check_deadlock());
183 }
184
185 #[test]
186 fn test_remutex_deadlock() {
187 let _guard = DEADLOCK_DETECTION_LOCK.lock();
188
189 let m1: Arc<ReentrantMutex<()>> = Default::default();
190 let m2: Arc<ReentrantMutex<()>> = Default::default();
191 let m3: Arc<ReentrantMutex<()>> = Default::default();
192 let b = Arc::new(Barrier::new(4));
193
194 let m1_ = m1.clone();
195 let m2_ = m2.clone();
196 let m3_ = m3.clone();
197 let b1 = b.clone();
198 let b2 = b.clone();
199 let b3 = b.clone();
200
201 assert!(!check_deadlock());
202
203 let _t1 = thread::spawn(move || {
204 let _g = m1.lock();
205 let _g = m1.lock();
206 b1.wait();
207 let _ = m2_.lock();
208 });
209
210 let _t2 = thread::spawn(move || {
211 let _g = m2.lock();
212 let _g = m2.lock();
213 b2.wait();
214 let _ = m3_.lock();
215 });
216
217 let _t3 = thread::spawn(move || {
218 let _g = m3.lock();
219 let _g = m3.lock();
220 b3.wait();
221 let _ = m1_.lock();
222 });
223
224 assert!(!check_deadlock());
225
226 b.wait();
227 sleep(Duration::from_millis(50));
228 assert_deadlock(3);
229
230 assert!(!check_deadlock());
231 }
232
233 #[test]
234 fn test_rwlock_deadlock() {
235 let _guard = DEADLOCK_DETECTION_LOCK.lock();
236
237 let m1: Arc<RwLock<()>> = Default::default();
238 let m2: Arc<RwLock<()>> = Default::default();
239 let m3: Arc<RwLock<()>> = Default::default();
240 let b = Arc::new(Barrier::new(4));
241
242 let m1_ = m1.clone();
243 let m2_ = m2.clone();
244 let m3_ = m3.clone();
245 let b1 = b.clone();
246 let b2 = b.clone();
247 let b3 = b.clone();
248
249 assert!(!check_deadlock());
250
251 let _t1 = thread::spawn(move || {
252 let _g = m1.read();
253 b1.wait();
254 let _g = m2_.write();
255 });
256
257 let _t2 = thread::spawn(move || {
258 let _g = m2.read();
259 b2.wait();
260 let _g = m3_.write();
261 });
262
263 let _t3 = thread::spawn(move || {
264 let _g = m3.read();
265 b3.wait();
266 let _blocked = m1_.write();
267 });
268
269 assert!(!check_deadlock());
270
271 b.wait();
272 sleep(Duration::from_millis(50));
273 assert_deadlock(3);
274
275 assert!(!check_deadlock());
276 }
277
278 #[test]
279 fn test_rwlock_deadlock_reentrant() {
280 let _guard = DEADLOCK_DETECTION_LOCK.lock();
281
282 let m1: Arc<RwLock<()>> = Default::default();
283
284 assert!(!check_deadlock());
285
286 let _t1 = thread::spawn(move || {
287 let _g = m1.read();
288 let _ = m1.write();
289 });
290
291 sleep(Duration::from_millis(50));
292 assert_deadlock(1);
293
294 assert!(!check_deadlock());
295 }
296
297 #[test]
298 fn test_rwlock_shared_reader_does_not_own_primary_key() {
299 let _guard = DEADLOCK_DETECTION_LOCK.lock();
300
301 let rwlock: Arc<RwLock<()>> = Default::default();
302 let mutex: Arc<Mutex<()>> = Default::default();
303 let (upgradable_ready_tx, upgradable_ready_rx) = mpsc::channel();
304 let (release_upgradable_tx, release_upgradable_rx) = mpsc::channel();
305 let (reader_ready_tx, reader_ready_rx) = mpsc::channel();
306
307 let rwlock1 = Arc::clone(&rwlock);
308 let upgradable = thread::spawn(move || {
309 let _guard = rwlock1.upgradable_read();
310 upgradable_ready_tx.send(()).unwrap();
311 release_upgradable_rx.recv().unwrap();
312 });
313 upgradable_ready_rx.recv().unwrap();
314
315 let rwlock2 = Arc::clone(&rwlock);
316 let mutex1 = Arc::clone(&mutex);
317 let blocked_upgradable = thread::spawn(move || {
318 let _guard = mutex1.lock();
319 let _blocked = rwlock2.upgradable_read();
320 });
321 while !unsafe { rwlock.raw() }.has_parked_threads() {
322 thread::yield_now();
323 }
324
325 let rwlock3 = Arc::clone(&rwlock);
326 let mutex2 = Arc::clone(&mutex);
327 let reader = thread::spawn(move || {
328 let _guard = rwlock3.read();
329 reader_ready_tx.send(()).unwrap();
330 let _blocked = mutex2.lock();
331 });
332 reader_ready_rx.recv().unwrap();
333
334 sleep(Duration::from_millis(50));
335 assert!(!check_deadlock());
336
337 release_upgradable_tx.send(()).unwrap();
338 upgradable.join().unwrap();
339 blocked_upgradable.join().unwrap();
340 reader.join().unwrap();
341 }
342
343 #[test]
344 fn test_rwlock_pending_writer_owns_primary_key() {
345 let _guard = DEADLOCK_DETECTION_LOCK.lock();
346
347 let rwlock: Arc<RwLock<()>> = Default::default();
348 let mutex: Arc<Mutex<()>> = Default::default();
349 let (reader_ready_tx, reader_ready_rx) = mpsc::channel();
350 let (block_reader_tx, block_reader_rx) = mpsc::channel();
351 let (mutex_ready_tx, mutex_ready_rx) = mpsc::channel();
352
353 let rwlock1 = Arc::clone(&rwlock);
354 let mutex1 = Arc::clone(&mutex);
355 let _reader = thread::spawn(move || {
356 let _guard = rwlock1.read();
357 reader_ready_tx.send(()).unwrap();
358 block_reader_rx.recv().unwrap();
359 let _blocked = mutex1.lock();
360 });
361 reader_ready_rx.recv().unwrap();
362
363 let rwlock2 = Arc::clone(&rwlock);
364 let _writer = thread::spawn(move || {
365 let _blocked = rwlock2.write();
366 });
367 while !unsafe { rwlock.raw() }.has_parked_threads() {
368 thread::yield_now();
369 }
370
371 let rwlock3 = Arc::clone(&rwlock);
372 let _blocked_reader = thread::spawn(move || {
373 let _guard = mutex.lock();
374 mutex_ready_tx.send(()).unwrap();
375 let _blocked = rwlock3.read();
376 });
377 mutex_ready_rx.recv().unwrap();
378 block_reader_tx.send(()).unwrap();
379
380 sleep(Duration::from_millis(50));
381 assert_deadlock(3);
382 assert!(!check_deadlock());
383 }
384}