From a3f4d93903732f3ae3baec2815e3d3305abdcbf6 Mon Sep 17 00:00:00 2001
From: John Hodge <tpg@mutabah.net>
Date: Sun, 30 Sep 2018 10:56:25 +0800
Subject: [PATCH] Kernel - Detect recursive mutex locks

---
 Kernel/Core/sync/mutex.rs  | 5 +++++
 Kernel/Core/threads/mod.rs | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Kernel/Core/sync/mutex.rs b/Kernel/Core/sync/mutex.rs
index 48b72a50..bdc2ae7c 100644
--- a/Kernel/Core/sync/mutex.rs
+++ b/Kernel/Core/sync/mutex.rs
@@ -18,6 +18,7 @@ pub struct Mutex<T: Send>
 pub struct MutexInner
 {
 	held: bool,
+	holder: ::threads::ThreadID,
 	queue: ::threads::WaitQueue,
 }
 
@@ -44,6 +45,7 @@ impl<T: Send> Mutex<T>
 		Mutex {
 			inner: ::sync::Spinlock::new(MutexInner {
 				held: false,
+				holder: 0,
 				queue: ::threads::WaitQueue::new(),
 				}),
 			val: ::core::cell::UnsafeCell::new(val),
@@ -59,14 +61,17 @@ impl<T: Send> Mutex<T>
 			let mut lh = self.inner.lock();
 			if lh.held != false
 			{
+				assert!(lh.holder != ::threads::get_thread_id(), "Recursive lock of {}", type_name!(Self));
 				// If mutex is locked, then wait for it to be unlocked
 				// - ThreadList::wait will release the passed spinlock
 				waitqueue_wait_ext!(lh, .queue);
 				// lh.queue.wait(lh);	// << Trips borrowck
+				self.inner.lock().holder = ::threads::get_thread_id();
 			}
 			else
 			{
 				lh.held = true;
+				lh.holder = ::threads::get_thread_id();
 			}
 		}
 		::core::sync::atomic::fence(::core::sync::atomic::Ordering::Acquire);
diff --git a/Kernel/Core/threads/mod.rs b/Kernel/Core/threads/mod.rs
index 235628a8..ea830223 100644
--- a/Kernel/Core/threads/mod.rs
+++ b/Kernel/Core/threads/mod.rs
@@ -13,7 +13,7 @@ mod worker_thread;
 
 mod sleep_object;
 
-pub use self::thread::{Thread,ThreadPtr};
+pub use self::thread::{Thread,ThreadPtr,ThreadID};
 pub use self::thread::{ThreadHandle,ProcessHandle};
 pub use self::thread::new_idle_thread;
 
-- 
GitLab