Parcourir la source

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(..).
Brian Gianforcaro il y a 5 ans
Parent
commit
1f64e3eb16
3 fichiers modifiés avec 17 ajouts et 2 suppressions
  1. 1 2
      Kernel/Process.cpp
  2. 15 0
      Kernel/WaitQueue.cpp
  3. 1 0
      Kernel/WaitQueue.h

+ 1 - 2
Kernel/Process.cpp

@@ -4636,8 +4636,7 @@ int Process::sys$futex(const Syscall::SC_futex_params* user_params)
         if (value == 1) {
         if (value == 1) {
             futex_queue(userspace_address).wake_one();
             futex_queue(userspace_address).wake_one();
         } else {
         } else {
-            // FIXME: Wake exactly (value) waiters.
-            futex_queue(userspace_address).wake_all();
+            futex_queue(userspace_address).wake_n(value);
         }
         }
         break;
         break;
     }
     }

+ 15 - 0
Kernel/WaitQueue.cpp

@@ -55,6 +55,21 @@ void WaitQueue::wake_one(Atomic<bool>* lock)
     Scheduler::stop_idling();
     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()
 void WaitQueue::wake_all()
 {
 {
     InterruptDisabler disabler;
     InterruptDisabler disabler;

+ 1 - 0
Kernel/WaitQueue.h

@@ -39,6 +39,7 @@ public:
 
 
     void enqueue(Thread&);
     void enqueue(Thread&);
     void wake_one(Atomic<bool>* lock = nullptr);
     void wake_one(Atomic<bool>* lock = nullptr);
+    void wake_n(i32 wake_count);
     void wake_all();
     void wake_all();
     void clear();
     void clear();