From 1f64e3eb168df9e4ff67d78fec95a4f0f777b6ae Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Sat, 25 Apr 2020 16:57:12 -0700 Subject: [PATCH] Kernel: Implement FUTEX_WAKE of arbitrary count. Previously we just woke all waiters no matter how many were requested. Fix this by implementing WaitQueue::wake_n(..). --- Kernel/Process.cpp | 3 +-- Kernel/WaitQueue.cpp | 15 +++++++++++++++ Kernel/WaitQueue.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index c1c8483d0a2..34e85c72e99 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -4636,8 +4636,7 @@ int Process::sys$futex(const Syscall::SC_futex_params* user_params) if (value == 1) { futex_queue(userspace_address).wake_one(); } else { - // FIXME: Wake exactly (value) waiters. - futex_queue(userspace_address).wake_all(); + futex_queue(userspace_address).wake_n(value); } break; } diff --git a/Kernel/WaitQueue.cpp b/Kernel/WaitQueue.cpp index 2cafbb477fc..cc19acb117e 100644 --- a/Kernel/WaitQueue.cpp +++ b/Kernel/WaitQueue.cpp @@ -55,6 +55,21 @@ void WaitQueue::wake_one(Atomic* lock) Scheduler::stop_idling(); } +void WaitQueue::wake_n(i32 wake_count) +{ + InterruptDisabler disabler; + if (m_threads.is_empty()) + return; + + for (i32 i = 0; i < wake_count; ++i) { + Thread* thread = m_threads.take_first(); + if (!thread) + break; + thread->wake_from_queue(); + } + Scheduler::stop_idling(); +} + void WaitQueue::wake_all() { InterruptDisabler disabler; diff --git a/Kernel/WaitQueue.h b/Kernel/WaitQueue.h index faa77b62781..c4beae46178 100644 --- a/Kernel/WaitQueue.h +++ b/Kernel/WaitQueue.h @@ -39,6 +39,7 @@ public: void enqueue(Thread&); void wake_one(Atomic* lock = nullptr); + void wake_n(i32 wake_count); void wake_all(); void clear();