فهرست منبع

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.
Tom 4 سال پیش
والد
کامیت
0536a4ff41
1فایلهای تغییر یافته به همراه8 افزوده شده و 1 حذف شده
  1. 8 1
      Kernel/Thread.cpp

+ 8 - 1
Kernel/Thread.cpp

@@ -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);