impl deadlock detection

master
WangRunji 6 years ago
parent d28f54ce32
commit 9df9d01e68

@ -18,7 +18,7 @@ use crate::net::SOCKETS;
use crate::sync::SpinNoIrqLock as Mutex; use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET}; use crate::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
const AXI_STREAM_FIFO_ISR: *mut u32 = (KERNEL_OFFSET + 0x1820_0000) as *mut u32; const AXI_STREAM_FIFO_ISR: *mut u32 = (KERNEL_OFFSET + 0x1820_0000) as *mut u32;
const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32; const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32;

@ -28,6 +28,7 @@
use super::Condvar; use super::Condvar;
use crate::arch::interrupt; use crate::arch::interrupt;
use crate::processor;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::fmt; use core::fmt;
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
@ -35,11 +36,12 @@ use core::sync::atomic::{AtomicBool, Ordering};
pub type SpinLock<T> = Mutex<T, Spin>; pub type SpinLock<T> = Mutex<T, Spin>;
pub type SpinNoIrqLock<T> = Mutex<T, SpinNoIrq>; pub type SpinNoIrqLock<T> = Mutex<T, SpinNoIrq>;
pub type ThreadLock<T> = Mutex<T, Condvar>; pub type SleepLock<T> = Mutex<T, Condvar>;
pub struct Mutex<T: ?Sized, S: MutexSupport> { pub struct Mutex<T: ?Sized, S: MutexSupport> {
lock: AtomicBool, lock: AtomicBool,
support: S, support: S,
user: UnsafeCell<(usize, usize)>, // (cid, tid)
data: UnsafeCell<T>, data: UnsafeCell<T>,
} }
@ -78,6 +80,7 @@ impl<T, S: MutexSupport> Mutex<T, S> {
lock: AtomicBool::new(false), lock: AtomicBool::new(false),
data: UnsafeCell::new(user_data), data: UnsafeCell::new(user_data),
support: S::new(), support: S::new(),
user: UnsafeCell::new((0, 0)),
} }
} }
@ -93,12 +96,24 @@ impl<T, S: MutexSupport> Mutex<T, S> {
impl<T: ?Sized, S: MutexSupport> Mutex<T, S> { impl<T: ?Sized, S: MutexSupport> Mutex<T, S> {
fn obtain_lock(&self) { fn obtain_lock(&self) {
while self.lock.compare_and_swap(false, true, Ordering::Acquire) != false { while self.lock.compare_and_swap(false, true, Ordering::Acquire) != false {
let mut try_count = 0;
// Wait until the lock looks unlocked before retrying // Wait until the lock looks unlocked before retrying
while self.lock.load(Ordering::Relaxed) { while self.lock.load(Ordering::Relaxed) {
self.support.cpu_relax(); self.support.cpu_relax();
try_count += 1;
if try_count == 0x100000 {
let (cid, tid) = unsafe { *self.user.get() };
error!(
"Mutex: deadlock detected! locked by cpu {} thread {} @ {:?}",
cid, tid, self as *const Self
);
} }
} }
} }
let cid = crate::arch::cpu::id();
let tid = processor().tid_option().unwrap_or(0);
unsafe { self.user.get().write((cid, tid)) };
}
/// Locks the spinlock and returns a guard. /// Locks the spinlock and returns a guard.
/// ///

@ -3,7 +3,7 @@
//! The code is borrowed from [RustDoc - Dining Philosophers](https://doc.rust-lang.org/1.6.0/book/dining-philosophers.html) //! The code is borrowed from [RustDoc - Dining Philosophers](https://doc.rust-lang.org/1.6.0/book/dining-philosophers.html)
use crate::sync::Condvar; use crate::sync::Condvar;
use crate::sync::ThreadLock as Mutex; use crate::sync::SleepLock as Mutex;
use crate::thread; use crate::thread;
use alloc::vec; use alloc::vec;
use alloc::{sync::Arc, vec::Vec}; use alloc::{sync::Arc, vec::Vec};

Loading…
Cancel
Save