summaryrefslogtreecommitdiff
path: root/Kernel/Thread.cpp
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-07-05 15:46:51 -0600
committerAndreas Kling <kling@serenityos.org>2020-07-06 10:00:24 +0200
commit9725bda63ee7f4a3f2586ce41b174d6c51a23b58 (patch)
tree1a334aee9554e8f85c1cb2fabf47a3d768f01c69 /Kernel/Thread.cpp
parent2a82a25fecd5342710410c8a89a9b949e6068ce8 (diff)
downloadserenity-9725bda63ee7f4a3f2586ce41b174d6c51a23b58.zip
Kernel: Enhance WaitQueue to remember pending wakes
If WaitQueue::wake_all, WaitQueue::wake_one, or WaitQueue::wake_n is called but nobody is currently waiting, we should remember that fact and prevent someone from waiting after such a request. This solves a race condition where the Finalizer thread is notified to finalize a thread, but it is not (yet) waiting on this queue. Fixes #2693
Diffstat (limited to 'Kernel/Thread.cpp')
-rw-r--r--Kernel/Thread.cpp8
1 files changed, 7 insertions, 1 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index bf0dcaac4e..8f21bef644 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -872,12 +872,18 @@ Thread::BlockResult Thread::wait_on(WaitQueue& queue, const char* reason, timeva
// we need to wait until the scheduler lock is released again
{
ScopedSpinLock sched_lock(g_scheduler_lock);
+ if (!queue.enqueue(*Thread::current())) {
+ // The WaitQueue was already requested to wake someone when
+ // nobody was waiting. So return right away as we shouldn't
+ // be waiting
+ return BlockResult::NotBlocked;
+ }
+
did_unlock = unlock_process_if_locked();
if (lock)
*lock = false;
set_state(State::Queued);
m_wait_reason = reason;
- queue.enqueue(*Thread::current());
if (timeout) {