summaryrefslogtreecommitdiff
path: root/Kernel/Thread.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2020-01-12 18:46:41 +0100
committerAndreas Kling <awesomekling@gmail.com>2020-01-12 19:04:16 +0100
commit41376d46620710d4fc148b3eb3a2f4a12189c795 (patch)
tree74b562d4825f06dd1c09df227cfe726aea7a2300 /Kernel/Thread.cpp
parent61e6b1fb7c2770a2b5b56cbff5217adf8c2c4ee8 (diff)
downloadserenity-41376d46620710d4fc148b3eb3a2f4a12189c795.zip
Kernel: Fix Lock racing to the WaitQueue
There was a time window between releasing Lock::m_lock and calling into the lock's WaitQueue where someone else could take m_lock and bring two threads into a deadlock situation. Fix this issue by holding Lock::m_lock until interrupts are disabled by either Thread::wait_on() or WaitQueue::wake_one().
Diffstat (limited to 'Kernel/Thread.cpp')
-rw-r--r--Kernel/Thread.cpp4
1 files changed, 3 insertions, 1 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index 31e15d17b9..7e63c88ef9 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -783,10 +783,12 @@ const LogStream& operator<<(const LogStream& stream, const Thread& value)
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
}
-void Thread::wait_on(WaitQueue& queue, Thread* beneficiary, const char* reason)
+void Thread::wait_on(WaitQueue& queue, Atomic<bool>* lock, Thread* beneficiary, const char* reason)
{
bool did_unlock = unlock_process_if_locked();
cli();
+ if (lock)
+ *lock = false;
set_state(State::Queued);
queue.enqueue(*current);
// Yield and wait for the queue to wake us up again.