From b17754f998f225f3de9df59c917c7b88f81aaf22 Mon Sep 17 00:00:00 2001
From: Yuri Kunde Schlesner <yuriks@yuriks.net>
Date: Mon, 29 May 2017 14:42:27 -0700
Subject: [PATCH 1/4] Kernel: Extract dynamic Object pointer cast into its own
 function

---
 src/core/hle/kernel/kernel.h | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 94f2025a0..d8929259e 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -121,6 +121,18 @@ inline void intrusive_ptr_release(Object* object) {
 template <typename T>
 using SharedPtr = boost::intrusive_ptr<T>;
 
+/**
+ * Attempts to downcast the given Object pointer to a pointer to T.
+ * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
+ */
+template <typename T>
+inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
+    if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
+        return boost::static_pointer_cast<T>(std::move(object));
+    }
+    return nullptr;
+}
+
 /// Class that represents a Kernel object that a thread can be waiting on
 class WaitObject : public Object {
 public:
@@ -163,6 +175,15 @@ private:
     std::vector<SharedPtr<Thread>> waiting_threads;
 };
 
+// Specialization of DynamicObjectCast for WaitObjects
+template <>
+inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
+    if (object != nullptr && object->IsWaitable()) {
+        return boost::static_pointer_cast<WaitObject>(std::move(object));
+    }
+    return nullptr;
+}
+
 /**
  * This class allows the creation of Handles, which are references to objects that can be tested
  * for validity and looked up. Here they are used to pass references to kernel objects to/from the
@@ -224,15 +245,11 @@ public:
     /**
      * Looks up a handle while verifying its type.
      * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
-     *         type differs from the handle type `T::HANDLE_TYPE`.
+     *         type differs from the requested one.
      */
     template <class T>
     SharedPtr<T> Get(Handle handle) const {
-        SharedPtr<Object> object = GetGeneric(handle);
-        if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
-            return boost::static_pointer_cast<T>(std::move(object));
-        }
-        return nullptr;
+        return DynamicObjectCast<T>(GetGeneric(handle));
     }
 
     /**
@@ -241,11 +258,7 @@ public:
      *         not a waitable object.
      */
     SharedPtr<WaitObject> GetWaitObject(Handle handle) const {
-        SharedPtr<Object> object = GetGeneric(handle);
-        if (object != nullptr && object->IsWaitable()) {
-            return boost::static_pointer_cast<WaitObject>(std::move(object));
-        }
-        return nullptr;
+        return DynamicObjectCast<WaitObject>(GetGeneric(handle));
     }
 
     /// Closes all handles held in this table.

From 9453223075e100a94b274613f1da0c47f747edf5 Mon Sep 17 00:00:00 2001
From: Yuri Kunde Schlesner <yuriks@yuriks.net>
Date: Mon, 29 May 2017 15:10:06 -0700
Subject: [PATCH 2/4] Kernel: Removed HandleTable::GetWaitObject

This isn't necessary anymore since plain Get works correctly for
WaitObjects.
---
 src/core/hle/kernel/kernel.h | 9 ---------
 src/core/hle/svc.cpp         | 4 ++--
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d8929259e..4344264dc 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -252,15 +252,6 @@ public:
         return DynamicObjectCast<T>(GetGeneric(handle));
     }
 
-    /**
-     * Looks up a handle while verifying that it is an object that a thread can wait on
-     * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or it is
-     *         not a waitable object.
-     */
-    SharedPtr<WaitObject> GetWaitObject(Handle handle) const {
-        return DynamicObjectCast<WaitObject>(GetGeneric(handle));
-    }
-
     /// Closes all handles held in this table.
     void Clear();
 
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 30230d65a..243c54c6e 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -244,7 +244,7 @@ static ResultCode CloseHandle(Kernel::Handle handle) {
 
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) {
-    auto object = Kernel::g_handle_table.GetWaitObject(handle);
+    auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle);
     Kernel::Thread* thread = Kernel::GetCurrentThread();
 
     if (object == nullptr)
@@ -299,7 +299,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
     std::vector<ObjectPtr> objects(handle_count);
 
     for (int i = 0; i < handle_count; ++i) {
-        auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
+        auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]);
         if (object == nullptr)
             return ERR_INVALID_HANDLE;
         objects[i] = object;

From 64ecf81a3cf6d6e0a4e4e915e1da2f0bcf2f1cb4 Mon Sep 17 00:00:00 2001
From: Yuri Kunde Schlesner <yuriks@yuriks.net>
Date: Mon, 29 May 2017 15:45:30 -0700
Subject: [PATCH 3/4] Kernel: Move WaitObject to a separate file

Now that HandleTable doesn't directly depend on WaitObject anymore, this
can be separated from the main kernel.h header.
---
 src/citra_qt/debugger/wait_tree.cpp  |  1 +
 src/citra_qt/debugger/wait_tree.h    |  4 +-
 src/core/CMakeLists.txt              |  2 +
 src/core/hle/kernel/event.h          |  1 +
 src/core/hle/kernel/kernel.cpp       | 79 ----------------------
 src/core/hle/kernel/kernel.h         | 53 ---------------
 src/core/hle/kernel/mutex.h          |  1 +
 src/core/hle/kernel/semaphore.h      |  1 +
 src/core/hle/kernel/server_port.h    |  1 +
 src/core/hle/kernel/server_session.h |  1 +
 src/core/hle/kernel/thread.h         |  1 +
 src/core/hle/kernel/timer.h          |  1 +
 src/core/hle/kernel/wait_object.cpp  | 99 ++++++++++++++++++++++++++++
 src/core/hle/kernel/wait_object.h    | 67 +++++++++++++++++++
 src/core/hle/svc.cpp                 |  1 +
 15 files changed, 178 insertions(+), 135 deletions(-)
 create mode 100644 src/core/hle/kernel/wait_object.cpp
 create mode 100644 src/core/hle/kernel/wait_object.h

diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index b6ecf3819..8c244b6b2 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -10,6 +10,7 @@
 #include "core/hle/kernel/semaphore.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/timer.h"
+#include "core/hle/kernel/wait_object.h"
 
 WaitTreeItem::~WaitTreeItem() {}
 
diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h
index ee9708fc1..06ef58ea7 100644
--- a/src/citra_qt/debugger/wait_tree.h
+++ b/src/citra_qt/debugger/wait_tree.h
@@ -4,12 +4,10 @@
 
 #pragma once
 
-#include <boost/container/flat_set.hpp>
-
 #include <QAbstractItemModel>
 #include <QDockWidget>
 #include <QTreeView>
-
+#include <boost/container/flat_set.hpp>
 #include "core/core.h"
 #include "core/hle/kernel/kernel.h"
 
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7aa81e885..ba24a6e02 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -57,6 +57,7 @@ set(SRCS
             hle/kernel/thread.cpp
             hle/kernel/timer.cpp
             hle/kernel/vm_manager.cpp
+            hle/kernel/wait_object.cpp
             hle/service/ac/ac.cpp
             hle/service/ac/ac_i.cpp
             hle/service/ac/ac_u.cpp
@@ -249,6 +250,7 @@ set(HEADERS
             hle/kernel/thread.h
             hle/kernel/timer.h
             hle/kernel/vm_manager.h
+            hle/kernel/wait_object.h
             hle/result.h
             hle/service/ac/ac.h
             hle/service/ac/ac_i.h
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 3e3673508..cc41abb85 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -6,6 +6,7 @@
 
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7f84e01aa..b0af5b9b8 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -20,85 +20,6 @@ namespace Kernel {
 unsigned int Object::next_object_id;
 HandleTable g_handle_table;
 
-void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
-    auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
-    if (itr == waiting_threads.end())
-        waiting_threads.push_back(std::move(thread));
-}
-
-void WaitObject::RemoveWaitingThread(Thread* thread) {
-    auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
-    // If a thread passed multiple handles to the same object,
-    // the kernel might attempt to remove the thread from the object's
-    // waiting threads list multiple times.
-    if (itr != waiting_threads.end())
-        waiting_threads.erase(itr);
-}
-
-SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
-    Thread* candidate = nullptr;
-    s32 candidate_priority = THREADPRIO_LOWEST + 1;
-
-    for (const auto& thread : waiting_threads) {
-        // The list of waiting threads must not contain threads that are not waiting to be awakened.
-        ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
-                       thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
-                   "Inconsistent thread statuses in waiting_threads");
-
-        if (thread->current_priority >= candidate_priority)
-            continue;
-
-        if (ShouldWait(thread.get()))
-            continue;
-
-        // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
-        // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
-        bool ready_to_run = true;
-        if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
-            ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
-                                        [&thread](const SharedPtr<WaitObject>& object) {
-                                            return object->ShouldWait(thread.get());
-                                        });
-        }
-
-        if (ready_to_run) {
-            candidate = thread.get();
-            candidate_priority = thread->current_priority;
-        }
-    }
-
-    return candidate;
-}
-
-void WaitObject::WakeupAllWaitingThreads() {
-    while (auto thread = GetHighestPriorityReadyThread()) {
-        if (!thread->IsSleepingOnWaitAll()) {
-            Acquire(thread.get());
-            // Set the output index of the WaitSynchronizationN call to the index of this object.
-            if (thread->wait_set_output) {
-                thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
-                thread->wait_set_output = false;
-            }
-        } else {
-            for (auto& object : thread->wait_objects) {
-                object->Acquire(thread.get());
-            }
-            // Note: This case doesn't update the output index of WaitSynchronizationN.
-        }
-
-        for (auto& object : thread->wait_objects)
-            object->RemoveWaitingThread(thread.get());
-        thread->wait_objects.clear();
-
-        thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
-        thread->ResumeFromWait();
-    }
-}
-
-const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
-    return waiting_threads;
-}
-
 HandleTable::HandleTable() {
     next_generation = 1;
     Clear();
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 4344264dc..5335a961d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -17,8 +17,6 @@ namespace Kernel {
 
 using Handle = u32;
 
-class Thread;
-
 enum KernelHandle : Handle {
     CurrentThread = 0xFFFF8000,
     CurrentProcess = 0xFFFF8001,
@@ -133,57 +131,6 @@ inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
     return nullptr;
 }
 
-/// Class that represents a Kernel object that a thread can be waiting on
-class WaitObject : public Object {
-public:
-    /**
-     * Check if the specified thread should wait until the object is available
-     * @param thread The thread about which we're deciding.
-     * @return True if the current thread should wait due to this object being unavailable
-     */
-    virtual bool ShouldWait(Thread* thread) const = 0;
-
-    /// Acquire/lock the object for the specified thread if it is available
-    virtual void Acquire(Thread* thread) = 0;
-
-    /**
-     * Add a thread to wait on this object
-     * @param thread Pointer to thread to add
-     */
-    virtual void AddWaitingThread(SharedPtr<Thread> thread);
-
-    /**
-     * Removes a thread from waiting on this object (e.g. if it was resumed already)
-     * @param thread Pointer to thread to remove
-     */
-    virtual void RemoveWaitingThread(Thread* thread);
-
-    /**
-     * Wake up all threads waiting on this object that can be awoken, in priority order,
-     * and set the synchronization result and output of the thread.
-     */
-    virtual void WakeupAllWaitingThreads();
-
-    /// Obtains the highest priority thread that is ready to run from this object's waiting list.
-    SharedPtr<Thread> GetHighestPriorityReadyThread();
-
-    /// Get a const reference to the waiting threads list for debug use
-    const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
-
-private:
-    /// Threads waiting for this object to become available
-    std::vector<SharedPtr<Thread>> waiting_threads;
-};
-
-// Specialization of DynamicObjectCast for WaitObjects
-template <>
-inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
-    if (object != nullptr && object->IsWaitable()) {
-        return boost::static_pointer_cast<WaitObject>(std::move(object));
-    }
-    return nullptr;
-}
-
 /**
  * This class allows the creation of Handles, which are references to objects that can be tested
  * for validity and looked up. Here they are used to pass references to kernel objects to/from the
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index c57adf400..bacacd690 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -7,6 +7,7 @@
 #include <string>
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index cde94f7cc..ca6f908aa 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -8,6 +8,7 @@
 #include <string>
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 6f8bdb6a9..2a24d8412 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -9,6 +9,7 @@
 #include <tuple>
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 
 namespace Service {
 class SessionRequestHandler;
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index c907d487c..315b80d14 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -11,6 +11,7 @@
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/session.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/wait_object.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
 #include "core/memory.h"
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 7b5169cfc..6a3566f15 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -12,6 +12,7 @@
 #include "common/common_types.h"
 #include "core/arm/arm_interface.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 #include "core/hle/result.h"
 
 enum ThreadPriority : s32 {
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b0f818933..82552372d 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -6,6 +6,7 @@
 
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/wait_object.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
new file mode 100644
index 000000000..f245eda6c
--- /dev/null
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -0,0 +1,99 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/config_mem.h"
+#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/memory.h"
+#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/timer.h"
+#include "core/hle/shared_page.h"
+
+namespace Kernel {
+
+void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
+    auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
+    if (itr == waiting_threads.end())
+        waiting_threads.push_back(std::move(thread));
+}
+
+void WaitObject::RemoveWaitingThread(Thread* thread) {
+    auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
+    // If a thread passed multiple handles to the same object,
+    // the kernel might attempt to remove the thread from the object's
+    // waiting threads list multiple times.
+    if (itr != waiting_threads.end())
+        waiting_threads.erase(itr);
+}
+
+SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
+    Thread* candidate = nullptr;
+    s32 candidate_priority = THREADPRIO_LOWEST + 1;
+
+    for (const auto& thread : waiting_threads) {
+        // The list of waiting threads must not contain threads that are not waiting to be awakened.
+        ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
+                       thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
+                   "Inconsistent thread statuses in waiting_threads");
+
+        if (thread->current_priority >= candidate_priority)
+            continue;
+
+        if (ShouldWait(thread.get()))
+            continue;
+
+        // A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
+        // in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
+        bool ready_to_run = true;
+        if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
+            ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
+                                        [&thread](const SharedPtr<WaitObject>& object) {
+                                            return object->ShouldWait(thread.get());
+                                        });
+        }
+
+        if (ready_to_run) {
+            candidate = thread.get();
+            candidate_priority = thread->current_priority;
+        }
+    }
+
+    return candidate;
+}
+
+void WaitObject::WakeupAllWaitingThreads() {
+    while (auto thread = GetHighestPriorityReadyThread()) {
+        if (!thread->IsSleepingOnWaitAll()) {
+            Acquire(thread.get());
+            // Set the output index of the WaitSynchronizationN call to the index of this object.
+            if (thread->wait_set_output) {
+                thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
+                thread->wait_set_output = false;
+            }
+        } else {
+            for (auto& object : thread->wait_objects) {
+                object->Acquire(thread.get());
+            }
+            // Note: This case doesn't update the output index of WaitSynchronizationN.
+        }
+
+        for (auto& object : thread->wait_objects)
+            object->RemoveWaitingThread(thread.get());
+        thread->wait_objects.clear();
+
+        thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
+        thread->ResumeFromWait();
+    }
+}
+
+const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
+    return waiting_threads;
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
new file mode 100644
index 000000000..861578186
--- /dev/null
+++ b/src/core/hle/kernel/wait_object.h
@@ -0,0 +1,67 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include "common/common_types.h"
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+class Thread;
+
+/// Class that represents a Kernel object that a thread can be waiting on
+class WaitObject : public Object {
+public:
+    /**
+     * Check if the specified thread should wait until the object is available
+     * @param thread The thread about which we're deciding.
+     * @return True if the current thread should wait due to this object being unavailable
+     */
+    virtual bool ShouldWait(Thread* thread) const = 0;
+
+    /// Acquire/lock the object for the specified thread if it is available
+    virtual void Acquire(Thread* thread) = 0;
+
+    /**
+     * Add a thread to wait on this object
+     * @param thread Pointer to thread to add
+     */
+    virtual void AddWaitingThread(SharedPtr<Thread> thread);
+
+    /**
+     * Removes a thread from waiting on this object (e.g. if it was resumed already)
+     * @param thread Pointer to thread to remove
+     */
+    virtual void RemoveWaitingThread(Thread* thread);
+
+    /**
+     * Wake up all threads waiting on this object that can be awoken, in priority order,
+     * and set the synchronization result and output of the thread.
+     */
+    virtual void WakeupAllWaitingThreads();
+
+    /// Obtains the highest priority thread that is ready to run from this object's waiting list.
+    SharedPtr<Thread> GetHighestPriorityReadyThread();
+
+    /// Get a const reference to the waiting threads list for debug use
+    const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
+
+private:
+    /// Threads waiting for this object to become available
+    std::vector<SharedPtr<Thread>> waiting_threads;
+};
+
+// Specialization of DynamicObjectCast for WaitObjects
+template <>
+inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
+    if (object != nullptr && object->IsWaitable()) {
+        return boost::static_pointer_cast<WaitObject>(std::move(object));
+    }
+    return nullptr;
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 243c54c6e..83767677f 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -27,6 +27,7 @@
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/timer.h"
 #include "core/hle/kernel/vm_manager.h"
+#include "core/hle/kernel/wait_object.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
 

From be031989ee9384786fb9ed380dab9a260ad69fd5 Mon Sep 17 00:00:00 2001
From: Yuri Kunde Schlesner <yuriks@yuriks.net>
Date: Mon, 29 May 2017 16:45:42 -0700
Subject: [PATCH 4/4] Kernel: Move HandleTable to a separate file

---
 src/core/CMakeLists.txt                |   2 +
 src/core/hle/ipc_helpers.h             |   2 +
 src/core/hle/kernel/address_arbiter.h  |   1 +
 src/core/hle/kernel/client_port.h      |   1 +
 src/core/hle/kernel/client_session.h   |   3 +-
 src/core/hle/kernel/handle_table.cpp   |  97 +++++++++++++++++++
 src/core/hle/kernel/handle_table.h     | 126 +++++++++++++++++++++++++
 src/core/hle/kernel/kernel.cpp         |  85 +----------------
 src/core/hle/kernel/kernel.h           | 116 +----------------------
 src/core/hle/kernel/memory.cpp         |   1 +
 src/core/hle/kernel/resource_limit.cpp |   1 +
 src/core/hle/kernel/semaphore.h        |   1 +
 src/core/hle/kernel/server_session.h   |   2 +-
 src/core/hle/kernel/thread.cpp         |   1 +
 src/core/hle/kernel/timer.cpp          |   1 +
 src/core/hle/service/apt/apt.h         |   2 +
 src/core/hle/service/service.h         |   1 -
 src/core/hle/svc.cpp                   |   2 +
 18 files changed, 242 insertions(+), 203 deletions(-)
 create mode 100644 src/core/hle/kernel/handle_table.cpp
 create mode 100644 src/core/hle/kernel/handle_table.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ba24a6e02..bc3b429b3 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRCS
             hle/kernel/client_port.cpp
             hle/kernel/client_session.cpp
             hle/kernel/event.cpp
+            hle/kernel/handle_table.cpp
             hle/kernel/kernel.cpp
             hle/kernel/memory.cpp
             hle/kernel/mutex.cpp
@@ -237,6 +238,7 @@ set(HEADERS
             hle/kernel/client_session.h
             hle/kernel/errors.h
             hle/kernel/event.h
+            hle/kernel/handle_table.h
             hle/kernel/kernel.h
             hle/kernel/memory.h
             hle/kernel/mutex.h
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 06c4c5a85..d7348c09d 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -3,7 +3,9 @@
 // Refer to the license.txt file included.
 
 #pragma once
+
 #include "core/hle/ipc.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 
 namespace IPC {
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 6a7af93a9..1d24401b1 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -6,6 +6,7 @@
 
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
 
 // Address arbiters are an underlying kernel synchronization object that can be created/used via
 // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 511490c7c..8f7d6ac44 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -7,6 +7,7 @@
 #include <string>
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index 9f3adb72b..2de379c09 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -6,10 +6,9 @@
 
 #include <memory>
 #include <string>
-
 #include "common/common_types.h"
-
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
new file mode 100644
index 000000000..c7322d883
--- /dev/null
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -0,0 +1,97 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <utility>
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+HandleTable g_handle_table;
+
+HandleTable::HandleTable() {
+    next_generation = 1;
+    Clear();
+}
+
+ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
+    DEBUG_ASSERT(obj != nullptr);
+
+    u16 slot = next_free_slot;
+    if (slot >= generations.size()) {
+        LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
+        return ERR_OUT_OF_HANDLES;
+    }
+    next_free_slot = generations[slot];
+
+    u16 generation = next_generation++;
+
+    // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
+    // CTR-OS doesn't use generation 0, so skip straight to 1.
+    if (next_generation >= (1 << 15))
+        next_generation = 1;
+
+    generations[slot] = generation;
+    objects[slot] = std::move(obj);
+
+    Handle handle = generation | (slot << 15);
+    return MakeResult<Handle>(handle);
+}
+
+ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
+    SharedPtr<Object> object = GetGeneric(handle);
+    if (object == nullptr) {
+        LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
+        return ERR_INVALID_HANDLE;
+    }
+    return Create(std::move(object));
+}
+
+ResultCode HandleTable::Close(Handle handle) {
+    if (!IsValid(handle))
+        return ERR_INVALID_HANDLE;
+
+    u16 slot = GetSlot(handle);
+
+    objects[slot] = nullptr;
+
+    generations[slot] = next_free_slot;
+    next_free_slot = slot;
+    return RESULT_SUCCESS;
+}
+
+bool HandleTable::IsValid(Handle handle) const {
+    size_t slot = GetSlot(handle);
+    u16 generation = GetGeneration(handle);
+
+    return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
+}
+
+SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
+    if (handle == CurrentThread) {
+        return GetCurrentThread();
+    } else if (handle == CurrentProcess) {
+        return g_current_process;
+    }
+
+    if (!IsValid(handle)) {
+        return nullptr;
+    }
+    return objects[GetSlot(handle)];
+}
+
+void HandleTable::Clear() {
+    for (u16 i = 0; i < MAX_COUNT; ++i) {
+        generations[i] = i + 1;
+        objects[i] = nullptr;
+    }
+    next_free_slot = 0;
+}
+
+} // namespace
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
new file mode 100644
index 000000000..d6aaefbf7
--- /dev/null
+++ b/src/core/hle/kernel/handle_table.h
@@ -0,0 +1,126 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <cstddef>
+#include "common/common_types.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+enum KernelHandle : Handle {
+    CurrentThread = 0xFFFF8000,
+    CurrentProcess = 0xFFFF8001,
+};
+
+/**
+ * This class allows the creation of Handles, which are references to objects that can be tested
+ * for validity and looked up. Here they are used to pass references to kernel objects to/from the
+ * emulated process. it has been designed so that it follows the same handle format and has
+ * approximately the same restrictions as the handle manager in the CTR-OS.
+ *
+ * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
+ * The slot index is used to index into the arrays in this class to access the data corresponding
+ * to the Handle.
+ *
+ * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
+ * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
+ * value of the counter is stored into the Handle as well as in the handle table (in the
+ * "generations" array). When looking up a handle, the Handle's generation must match with the
+ * value stored on the class, otherwise the Handle is considered invalid.
+ *
+ * To find free slots when allocating a Handle without needing to scan the entire object array, the
+ * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
+ * When a Handle is created, an index is popped off the list and used for the new Handle. When it
+ * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
+ * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
+ * verified and isn't likely to cause any problems.
+ */
+class HandleTable final : NonCopyable {
+public:
+    HandleTable();
+
+    /**
+     * Allocates a handle for the given object.
+     * @return The created Handle or one of the following errors:
+     *           - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
+     */
+    ResultVal<Handle> Create(SharedPtr<Object> obj);
+
+    /**
+     * Returns a new handle that points to the same object as the passed in handle.
+     * @return The duplicated Handle or one of the following errors:
+     *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
+     *           - Any errors returned by `Create()`.
+     */
+    ResultVal<Handle> Duplicate(Handle handle);
+
+    /**
+     * Closes a handle, removing it from the table and decreasing the object's ref-count.
+     * @return `RESULT_SUCCESS` or one of the following errors:
+     *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
+     */
+    ResultCode Close(Handle handle);
+
+    /// Checks if a handle is valid and points to an existing object.
+    bool IsValid(Handle handle) const;
+
+    /**
+     * Looks up a handle.
+     * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
+     */
+    SharedPtr<Object> GetGeneric(Handle handle) const;
+
+    /**
+     * Looks up a handle while verifying its type.
+     * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
+     *         type differs from the requested one.
+     */
+    template <class T>
+    SharedPtr<T> Get(Handle handle) const {
+        return DynamicObjectCast<T>(GetGeneric(handle));
+    }
+
+    /// Closes all handles held in this table.
+    void Clear();
+
+private:
+    /**
+     * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
+     * reduced by ExHeader values, but this is not emulated here.
+     */
+    static const size_t MAX_COUNT = 4096;
+
+    static u16 GetSlot(Handle handle) {
+        return handle >> 15;
+    }
+    static u16 GetGeneration(Handle handle) {
+        return handle & 0x7FFF;
+    }
+
+    /// Stores the Object referenced by the handle or null if the slot is empty.
+    std::array<SharedPtr<Object>, MAX_COUNT> objects;
+
+    /**
+     * The value of `next_generation` when the handle was created, used to check for validity. For
+     * empty slots, contains the index of the next free slot in the list.
+     */
+    std::array<u16, MAX_COUNT> generations;
+
+    /**
+     * Global counter of the number of created handles. Stored in `generations` when a handle is
+     * created, and wraps around to 1 when it hits 0x8000.
+     */
+    u16 next_generation;
+
+    /// Head of the free slots linked list.
+    u16 next_free_slot;
+};
+
+extern HandleTable g_handle_table;
+
+} // namespace
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b0af5b9b8..7470a97ca 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,11 +2,8 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <algorithm>
-#include "common/assert.h"
-#include "common/logging/log.h"
 #include "core/hle/config_mem.h"
-#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/memory.h"
 #include "core/hle/kernel/process.h"
@@ -18,86 +15,6 @@
 namespace Kernel {
 
 unsigned int Object::next_object_id;
-HandleTable g_handle_table;
-
-HandleTable::HandleTable() {
-    next_generation = 1;
-    Clear();
-}
-
-ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
-    DEBUG_ASSERT(obj != nullptr);
-
-    u16 slot = next_free_slot;
-    if (slot >= generations.size()) {
-        LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
-        return ERR_OUT_OF_HANDLES;
-    }
-    next_free_slot = generations[slot];
-
-    u16 generation = next_generation++;
-
-    // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
-    // CTR-OS doesn't use generation 0, so skip straight to 1.
-    if (next_generation >= (1 << 15))
-        next_generation = 1;
-
-    generations[slot] = generation;
-    objects[slot] = std::move(obj);
-
-    Handle handle = generation | (slot << 15);
-    return MakeResult<Handle>(handle);
-}
-
-ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
-    SharedPtr<Object> object = GetGeneric(handle);
-    if (object == nullptr) {
-        LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
-        return ERR_INVALID_HANDLE;
-    }
-    return Create(std::move(object));
-}
-
-ResultCode HandleTable::Close(Handle handle) {
-    if (!IsValid(handle))
-        return ERR_INVALID_HANDLE;
-
-    u16 slot = GetSlot(handle);
-
-    objects[slot] = nullptr;
-
-    generations[slot] = next_free_slot;
-    next_free_slot = slot;
-    return RESULT_SUCCESS;
-}
-
-bool HandleTable::IsValid(Handle handle) const {
-    size_t slot = GetSlot(handle);
-    u16 generation = GetGeneration(handle);
-
-    return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
-}
-
-SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
-    if (handle == CurrentThread) {
-        return GetCurrentThread();
-    } else if (handle == CurrentProcess) {
-        return g_current_process;
-    }
-
-    if (!IsValid(handle)) {
-        return nullptr;
-    }
-    return objects[GetSlot(handle)];
-}
-
-void HandleTable::Clear() {
-    for (u16 i = 0; i < MAX_COUNT; ++i) {
-        generations[i] = i + 1;
-        objects[i] = nullptr;
-    }
-    next_free_slot = 0;
-}
 
 /// Initialize the kernel
 void Init(u32 system_mode) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 5335a961d..9cf288b08 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,24 +4,16 @@
 
 #pragma once
 
-#include <algorithm>
-#include <array>
 #include <cstddef>
 #include <string>
-#include <vector>
+#include <utility>
 #include <boost/smart_ptr/intrusive_ptr.hpp>
 #include "common/common_types.h"
-#include "core/hle/result.h"
 
 namespace Kernel {
 
 using Handle = u32;
 
-enum KernelHandle : Handle {
-    CurrentThread = 0xFFFF8000,
-    CurrentProcess = 0xFFFF8001,
-};
-
 enum class HandleType : u32 {
     Unknown,
     Event,
@@ -131,112 +123,6 @@ inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
     return nullptr;
 }
 
-/**
- * This class allows the creation of Handles, which are references to objects that can be tested
- * for validity and looked up. Here they are used to pass references to kernel objects to/from the
- * emulated process. it has been designed so that it follows the same handle format and has
- * approximately the same restrictions as the handle manager in the CTR-OS.
- *
- * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
- * The slot index is used to index into the arrays in this class to access the data corresponding
- * to the Handle.
- *
- * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
- * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
- * value of the counter is stored into the Handle as well as in the handle table (in the
- * "generations" array). When looking up a handle, the Handle's generation must match with the
- * value stored on the class, otherwise the Handle is considered invalid.
- *
- * To find free slots when allocating a Handle without needing to scan the entire object array, the
- * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
- * When a Handle is created, an index is popped off the list and used for the new Handle. When it
- * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
- * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
- * verified and isn't likely to cause any problems.
- */
-class HandleTable final : NonCopyable {
-public:
-    HandleTable();
-
-    /**
-     * Allocates a handle for the given object.
-     * @return The created Handle or one of the following errors:
-     *           - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
-     */
-    ResultVal<Handle> Create(SharedPtr<Object> obj);
-
-    /**
-     * Returns a new handle that points to the same object as the passed in handle.
-     * @return The duplicated Handle or one of the following errors:
-     *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
-     *           - Any errors returned by `Create()`.
-     */
-    ResultVal<Handle> Duplicate(Handle handle);
-
-    /**
-     * Closes a handle, removing it from the table and decreasing the object's ref-count.
-     * @return `RESULT_SUCCESS` or one of the following errors:
-     *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
-     */
-    ResultCode Close(Handle handle);
-
-    /// Checks if a handle is valid and points to an existing object.
-    bool IsValid(Handle handle) const;
-
-    /**
-     * Looks up a handle.
-     * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
-     */
-    SharedPtr<Object> GetGeneric(Handle handle) const;
-
-    /**
-     * Looks up a handle while verifying its type.
-     * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
-     *         type differs from the requested one.
-     */
-    template <class T>
-    SharedPtr<T> Get(Handle handle) const {
-        return DynamicObjectCast<T>(GetGeneric(handle));
-    }
-
-    /// Closes all handles held in this table.
-    void Clear();
-
-private:
-    /**
-     * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
-     * reduced by ExHeader values, but this is not emulated here.
-     */
-    static const size_t MAX_COUNT = 4096;
-
-    static u16 GetSlot(Handle handle) {
-        return handle >> 15;
-    }
-    static u16 GetGeneration(Handle handle) {
-        return handle & 0x7FFF;
-    }
-
-    /// Stores the Object referenced by the handle or null if the slot is empty.
-    std::array<SharedPtr<Object>, MAX_COUNT> objects;
-
-    /**
-     * The value of `next_generation` when the handle was created, used to check for validity. For
-     * empty slots, contains the index of the next free slot in the list.
-     */
-    std::array<u16, MAX_COUNT> generations;
-
-    /**
-     * Global counter of the number of created handles. Stored in `generations` when a handle is
-     * created, and wraps around to 1 when it hits 0x8000.
-     */
-    u16 next_generation;
-
-    /// Head of the free slots linked list.
-    u16 next_free_slot;
-};
-
-extern HandleTable g_handle_table;
-
 /// Initialize the kernel with the specified system mode.
 void Init(u32 system_mode);
 
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 8250a90b5..804f23b1c 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <algorithm>
 #include <cinttypes>
 #include <map>
 #include <memory>
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 3f51bc5de..a8f10a3ee 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <cstring>
+#include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/hle/kernel/resource_limit.h"
 
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index ca6f908aa..7b0cacf2e 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -9,6 +9,7 @@
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/wait_object.h"
+#include "core/hle/result.h"
 
 namespace Kernel {
 
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 315b80d14..f1b76d8aa 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -10,7 +10,6 @@
 #include "common/common_types.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/session.h"
-#include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/wait_object.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
@@ -21,6 +20,7 @@ namespace Kernel {
 class ClientSession;
 class ClientPort;
 class ServerSession;
+class Thread;
 
 /**
  * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 519ff51a8..75ce626f8 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -15,6 +15,7 @@
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/memory.h"
 #include "core/hle/kernel/mutex.h"
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index a00c75679..6f2cf3b02 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -6,6 +6,7 @@
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core_timing.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/timer.h"
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index e63b61450..ee80926d2 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <vector>
+#include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
 #include "core/hle/kernel/kernel.h"
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e6a5f1417..ffabc24a4 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -12,7 +12,6 @@
 #include "core/hle/ipc.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/thread.h"
 #include "core/hle/result.h"
 #include "core/memory.h"
 
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 83767677f..e68b9f16a 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <algorithm>
 #include <cinttypes>
 #include <map>
 #include "common/logging/log.h"
@@ -16,6 +17,7 @@
 #include "core/hle/kernel/client_session.h"
 #include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/event.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/memory.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/process.h"