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.
This commit is contained in:
Tom 2021-07-15 19:38:07 -06:00 committed by Andreas Kling
parent 710cf14c55
commit 0536a4ff41
Notes: sideshowbarker 2024-07-18 08:55:31 +09:00

View file

@ -211,11 +211,18 @@ void Thread::block(Kernel::Lock& lock, ScopedSpinLock<SpinLock<u8>>& 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);