From 0536a4ff413e8bf9f81ca313ef7a67e345f39be4 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 15 Jul 2021 19:38:07 -0600 Subject: [PATCH] Kernel: Release big lock when blocking on another lock When blocking on a Lock other than the big lock and we're holding the big lock, we need to release the big lock first. This fixes some deadlocks where a thread blocks while holding the big lock, preventing other threads from getting the big lock in order to unblock the waiting thread. --- Kernel/Thread.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 4ea2cfaa03..e4bb3dc8c4 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -211,11 +211,18 @@ void Thread::block(Kernel::Lock& lock, ScopedSpinLock>& lock_lock, dbgln_if(THREAD_DEBUG, "Thread {} blocking on Lock {}", *this, &lock); + auto& big_lock = process().big_lock(); for (;;) { // Yield to the scheduler, and wait for us to resume unblocked. VERIFY(!g_scheduler_lock.own_lock()); VERIFY(Processor::current().in_critical()); - yield_while_not_holding_big_lock(); // We might hold the big lock though! + if (&lock != &big_lock && big_lock.own_lock()) { + // We're locking another lock and already hold the big lock... + // We need to release the big lock + yield_without_holding_big_lock(); + } else { + yield_while_not_holding_big_lock(); + } VERIFY(Processor::current().in_critical()); ScopedSpinLock block_lock2(m_block_lock);