summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-01-30 12:16:14 +0100
committerAndreas Kling <kling@serenityos.org>2022-01-30 16:21:59 +0100
commit09f084371601d57c591dee2934f9b5bf6086c3a0 (patch)
tree683b9da2cff75a9828ae8c631681d087a9eac3ee
parentb0e5406ae2f9a895b057086f8d030255c68c9d04 (diff)
downloadserenity-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.cpp37
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;
}