diff options
author | Tom <tomut@yahoo.com> | 2020-07-05 15:46:51 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-06 10:00:24 +0200 |
commit | 9725bda63ee7f4a3f2586ce41b174d6c51a23b58 (patch) | |
tree | 1a334aee9554e8f85c1cb2fabf47a3d768f01c69 /Kernel/Thread.cpp | |
parent | 2a82a25fecd5342710410c8a89a9b949e6068ce8 (diff) | |
download | serenity-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.cpp | 8 |
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) { |