diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index c1c8483d0a..34e85c72e9 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 2cafbb477f..cc19acb117 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 faa77b6278..c4beae4617 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();