diff options
author | Andreas Kling <kling@serenityos.org> | 2022-01-30 12:16:14 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-01-30 16:21:59 +0100 |
commit | 09f084371601d57c591dee2934f9b5bf6086c3a0 (patch) | |
tree | 683b9da2cff75a9828ae8c631681d087a9eac3ee | |
parent | b0e5406ae2f9a895b057086f8d030255c68c9d04 (diff) | |
download | serenity-09f084371601d57c591dee2934f9b5bf6086c3a0.zip |
Kernel: Enforce that Thread::unblock_from_mutex() doesn't happen in IRQ
Mutexes are not usable from IRQ handlers, so unblock_from_mutex()
can simply VERIFY() that the current processor is not in an IRQ.
-rw-r--r-- | Kernel/Thread.cpp | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index b335798f61..caaea6ed1d 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -331,36 +331,23 @@ void Thread::block(Kernel::Mutex& lock, SpinlockLocker<Spinlock>& lock_lock, u32 u32 Thread::unblock_from_mutex(Kernel::Mutex& mutex) { + SpinlockLocker scheduler_lock(g_scheduler_lock); SpinlockLocker block_lock(m_block_lock); + + VERIFY(!Processor::current_in_irq()); VERIFY(m_blocking_mutex == &mutex); + + dbgln_if(THREAD_DEBUG, "Thread {} unblocked from Mutex {}", *this, &mutex); + auto requested_count = m_lock_requested_count; - block_lock.unlock(); - auto do_unblock = [&]() { - SpinlockLocker scheduler_lock(g_scheduler_lock); - SpinlockLocker block_lock(m_block_lock); - VERIFY(m_blocking_mutex == &mutex); - VERIFY(!Processor::current_in_irq()); - VERIFY(g_scheduler_lock.is_locked_by_current_processor()); - VERIFY(m_block_lock.is_locked_by_current_processor()); - VERIFY(m_blocking_mutex == &mutex); - dbgln_if(THREAD_DEBUG, "Thread {} unblocked from Mutex {}", *this, &mutex); - m_blocking_mutex = nullptr; - if (Thread::current() == this) { - set_state(Thread::State::Running); - return; - } - VERIFY(m_state != Thread::State::Runnable && m_state != Thread::State::Running); - set_state(Thread::State::Runnable); - }; - if (Processor::current_in_irq() != 0) { - Processor::deferred_call_queue([do_unblock = move(do_unblock), self = make_weak_ptr()]() { - if (auto this_thread = self.strong_ref()) - do_unblock(); - }); - } else { - do_unblock(); + m_blocking_mutex = nullptr; + if (Thread::current() == this) { + set_state(Thread::State::Running); + return requested_count; } + VERIFY(m_state != Thread::State::Runnable && m_state != Thread::State::Running); + set_state(Thread::State::Runnable); return requested_count; } |