Ver Fonte

Kernel: Use IntrusiveList to make WaitQueue allocation-free :^)

Andreas Kling há 5 anos atrás
pai
commit
f4978b2be1
4 ficheiros alterados com 30 adições e 26 exclusões
  1. 22 0
      Kernel/Thread.cpp
  2. 4 22
      Kernel/Thread.h
  3. 1 1
      Kernel/WaitQueue.cpp
  4. 3 3
      Kernel/WaitQueue.h

+ 22 - 0
Kernel/Thread.cpp

@@ -776,3 +776,25 @@ const char* to_string(ThreadPriority priority)
     ASSERT_NOT_REACHED();
     return nullptr;
 }
+
+void Thread::wait_on(WaitQueue& queue, Thread* beneficiary, const char* reason)
+{
+    bool did_unlock = unlock_process_if_locked();
+    cli();
+    set_state(State::Queued);
+    queue.enqueue(*current);
+    // Yield and wait for the queue to wake us up again.
+    if (beneficiary)
+        Scheduler::donate_to(beneficiary, reason);
+    else
+        Scheduler::yield();
+    // We've unblocked, relock the process if needed and carry on.
+    if (did_unlock)
+        relock_process();
+}
+
+void Thread::wake_from_queue()
+{
+    ASSERT(state() == State::Queued);
+    set_state(State::Runnable);
+}

+ 4 - 22
Kernel/Thread.h

@@ -11,7 +11,6 @@
 #include <Kernel/Scheduler.h>
 #include <Kernel/UnixTypes.h>
 #include <Kernel/VM/Region.h>
-#include <Kernel/WaitQueue.h>
 #include <LibC/fd_set.h>
 
 class Alarm;
@@ -291,27 +290,8 @@ public:
         return block<ConditionBlocker>(state_string, move(condition));
     }
 
-    void wait_on(WaitQueue& queue, Thread* beneficiary = nullptr, const char* reason = nullptr)
-    {
-        bool did_unlock = unlock_process_if_locked();
-        cli();
-        set_state(State::Queued);
-        queue.enqueue(*current);
-        // Yield and wait for the queue to wake us up again.
-        if (beneficiary)
-            Scheduler::donate_to(beneficiary, reason);
-        else
-            Scheduler::yield();
-        // We've unblocked, relock the process if needed and carry on.
-        if (did_unlock)
-            relock_process();
-    }
-
-    void wake_from_queue()
-    {
-        ASSERT(state() == State::Queued);
-        set_state(State::Runnable);
-    }
+    void wait_on(WaitQueue& queue, Thread* beneficiary = nullptr, const char* reason = nullptr);
+    void wake_from_queue();
 
     void unblock();
 
@@ -423,9 +403,11 @@ public:
 
 private:
     IntrusiveListNode m_runnable_list_node;
+    IntrusiveListNode m_wait_queue_node;
 
 private:
     friend class SchedulerData;
+    friend class WaitQueue;
     bool unlock_process_if_locked();
     void relock_process();
 

+ 1 - 1
Kernel/WaitQueue.cpp

@@ -12,7 +12,7 @@ WaitQueue::~WaitQueue()
 void WaitQueue::enqueue(Thread& thread)
 {
     InterruptDisabler disabler;
-    m_threads.append(&thread);
+    m_threads.append(thread);
 }
 
 void WaitQueue::wake_one()

+ 3 - 3
Kernel/WaitQueue.h

@@ -1,8 +1,7 @@
 #pragma once
 
 #include <AK/SinglyLinkedList.h>
-
-class Thread;
+#include <Kernel/Thread.h>
 
 class WaitQueue {
 public:
@@ -14,5 +13,6 @@ public:
     void wake_all();
 
 private:
-    SinglyLinkedList<Thread*> m_threads;
+    typedef IntrusiveList<Thread, &Thread::m_wait_queue_node> ThreadList;
+    ThreadList m_threads;
 };