Просмотр исходного кода

Merge pull request #523 from yuriks/kernel-lifetime5

Kernel Lifetime Reform Pt. 5: The Reckoning
bunnei 11 лет назад
Родитель
Сommit
7f730ed158
71 измененных файлов с 368 добавлено и 373 удалено
  1. 1 1
      externals/boost
  2. 1 0
      src/core/CMakeLists.txt
  3. 7 6
      src/core/hle/kernel/address_arbiter.cpp
  4. 3 2
      src/core/hle/kernel/address_arbiter.h
  5. 5 4
      src/core/hle/kernel/event.cpp
  6. 3 2
      src/core/hle/kernel/event.h
  7. 8 9
      src/core/hle/kernel/kernel.cpp
  8. 11 10
      src/core/hle/kernel/kernel.h
  9. 14 27
      src/core/hle/kernel/mutex.cpp
  10. 4 3
      src/core/hle/kernel/mutex.h
  11. 3 2
      src/core/hle/kernel/semaphore.cpp
  12. 2 1
      src/core/hle/kernel/semaphore.h
  13. 13 0
      src/core/hle/kernel/session.cpp
  14. 4 0
      src/core/hle/kernel/session.h
  15. 9 8
      src/core/hle/kernel/shared_memory.cpp
  16. 3 2
      src/core/hle/kernel/shared_memory.h
  17. 25 28
      src/core/hle/kernel/thread.cpp
  18. 21 10
      src/core/hle/kernel/thread.h
  19. 17 11
      src/core/hle/kernel/timer.cpp
  20. 6 2
      src/core/hle/kernel/timer.h
  21. 1 1
      src/core/hle/service/ac_u.cpp
  22. 1 1
      src/core/hle/service/act_u.cpp
  23. 1 1
      src/core/hle/service/am_app.cpp
  24. 1 1
      src/core/hle/service/am_net.cpp
  25. 1 1
      src/core/hle/service/am_sys.cpp
  26. 1 1
      src/core/hle/service/apt_a.cpp
  27. 1 1
      src/core/hle/service/apt_s.cpp
  28. 5 5
      src/core/hle/service/apt_u.cpp
  29. 1 1
      src/core/hle/service/boss_p.cpp
  30. 1 1
      src/core/hle/service/boss_u.cpp
  31. 1 1
      src/core/hle/service/cam_u.cpp
  32. 1 1
      src/core/hle/service/cecd_s.cpp
  33. 1 1
      src/core/hle/service/cecd_u.cpp
  34. 1 1
      src/core/hle/service/cfg/cfg_i.cpp
  35. 1 1
      src/core/hle/service/cfg/cfg_s.cpp
  36. 1 1
      src/core/hle/service/cfg/cfg_u.cpp
  37. 1 1
      src/core/hle/service/csnd_snd.cpp
  38. 2 3
      src/core/hle/service/dsp_dsp.cpp
  39. 1 1
      src/core/hle/service/err_f.cpp
  40. 1 1
      src/core/hle/service/frd_a.cpp
  41. 1 1
      src/core/hle/service/frd_u.cpp
  42. 9 17
      src/core/hle/service/fs/archive.cpp
  43. 10 4
      src/core/hle/service/fs/archive.h
  44. 16 13
      src/core/hle/service/fs/fs_user.cpp
  45. 2 2
      src/core/hle/service/gsp_gpu.cpp
  46. 1 1
      src/core/hle/service/gsp_lcd.cpp
  47. 8 6
      src/core/hle/service/hid/hid.cpp
  48. 1 1
      src/core/hle/service/hid/hid_spvr.cpp
  49. 1 1
      src/core/hle/service/hid/hid_user.cpp
  50. 1 1
      src/core/hle/service/http_c.cpp
  51. 1 1
      src/core/hle/service/ir_rst.cpp
  52. 1 1
      src/core/hle/service/ir_u.cpp
  53. 1 1
      src/core/hle/service/ldr_ro.cpp
  54. 1 1
      src/core/hle/service/mic_u.cpp
  55. 1 1
      src/core/hle/service/ndm_u.cpp
  56. 1 1
      src/core/hle/service/news_s.cpp
  57. 1 1
      src/core/hle/service/news_u.cpp
  58. 1 1
      src/core/hle/service/nim_aoc.cpp
  59. 1 1
      src/core/hle/service/ns_s.cpp
  60. 1 1
      src/core/hle/service/nwm_uds.cpp
  61. 1 1
      src/core/hle/service/pm_app.cpp
  62. 1 1
      src/core/hle/service/ptm_play.cpp
  63. 1 1
      src/core/hle/service/ptm_sysm.cpp
  64. 1 1
      src/core/hle/service/ptm_u.cpp
  65. 55 75
      src/core/hle/service/service.cpp
  66. 21 52
      src/core/hle/service/service.h
  67. 1 1
      src/core/hle/service/soc_u.cpp
  68. 5 5
      src/core/hle/service/srv.cpp
  69. 1 1
      src/core/hle/service/ssl_c.cpp
  70. 1 1
      src/core/hle/service/y2r_u.cpp
  71. 35 23
      src/core/hle/svc.cpp

+ 1 - 1
externals/boost

@@ -1 +1 @@
-Subproject commit a1afc91d3aaa3da06bdbc13c78613e1466653405
+Subproject commit 728a4d7d1c8b28355544ae829df9c4b5f28373c5

+ 1 - 0
src/core/CMakeLists.txt

@@ -26,6 +26,7 @@ set(SRCS
             hle/kernel/kernel.cpp
             hle/kernel/mutex.cpp
             hle/kernel/semaphore.cpp
+            hle/kernel/session.cpp
             hle/kernel/shared_memory.cpp
             hle/kernel/timer.cpp
             hle/kernel/thread.cpp

+ 7 - 6
src/core/hle/kernel/address_arbiter.cpp

@@ -15,14 +15,15 @@
 
 namespace Kernel {
 
-ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) {
+AddressArbiter::AddressArbiter() {}
+AddressArbiter::~AddressArbiter() {}
+
+SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
     SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter));
 
     address_arbiter->name = std::move(name);
 
-    return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter));
+    return address_arbiter;
 }
 
 ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
@@ -51,7 +52,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
     case ArbitrationType::WaitIfLessThanWithTimeout:
         if ((s32)Memory::Read32(address) <= value) {
             Kernel::WaitCurrentThread_ArbitrateAddress(address);
-            Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds);
+            GetCurrentThread()->WakeAfterDelay(nanoseconds);
             HLE::Reschedule(__func__);
         }
         break;
@@ -71,7 +72,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
         Memory::Write32(address, memory_value);
         if (memory_value <= value) {
             Kernel::WaitCurrentThread_ArbitrateAddress(address);
-            Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds);
+            GetCurrentThread()->WakeAfterDelay(nanoseconds);
             HLE::Reschedule(__func__);
         }
         break;

+ 3 - 2
src/core/hle/kernel/address_arbiter.h

@@ -34,7 +34,7 @@ public:
      * @param name Optional name used for debugging.
      * @returns The created AddressArbiter.
      */
-    static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown");
+    static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
 
     std::string GetTypeName() const override { return "Arbiter"; }
     std::string GetName() const override { return name; }
@@ -47,7 +47,8 @@ public:
     ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
 
 private:
-    AddressArbiter() = default;
+    AddressArbiter();
+    ~AddressArbiter() override;
 };
 
 } // namespace FileSys

+ 5 - 4
src/core/hle/kernel/event.cpp

@@ -14,16 +14,17 @@
 
 namespace Kernel {
 
-ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) {
+Event::Event() {}
+Event::~Event() {}
+
+SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
     SharedPtr<Event> evt(new Event);
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt));
 
     evt->signaled = false;
     evt->reset_type = evt->intitial_reset_type = reset_type;
     evt->name = std::move(name);
 
-    return MakeResult<SharedPtr<Event>>(evt);
+    return evt;
 }
 
 bool Event::ShouldWait() {

+ 3 - 2
src/core/hle/kernel/event.h

@@ -18,7 +18,7 @@ public:
      * @param reset_type ResetType describing how to create event
      * @param name Optional name of event
      */
-    static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown");
+    static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
 
     std::string GetTypeName() const override { return "Event"; }
     std::string GetName() const override { return name; }
@@ -39,7 +39,8 @@ public:
     void Clear();
 
 private:
-    Event() = default;
+    Event();
+    ~Event() override;
 };
 
 } // namespace

+ 8 - 9
src/core/hle/kernel/kernel.cpp

@@ -14,14 +14,16 @@
 
 namespace Kernel {
 
+unsigned int Object::next_object_id = 0;
+
 SharedPtr<Thread> g_main_thread = nullptr;
 HandleTable g_handle_table;
 u64 g_program_id = 0;
 
-void WaitObject::AddWaitingThread(Thread* thread) {
+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(thread);
+        waiting_threads.push_back(std::move(thread));
 }
 
 void WaitObject::RemoveWaitingThread(Thread* thread) {
@@ -30,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
         waiting_threads.erase(itr);
 }
 
-Thread* WaitObject::WakeupNextThread() {
+SharedPtr<Thread> WaitObject::WakeupNextThread() {
     if (waiting_threads.empty())
         return nullptr;
 
-    auto next_thread = waiting_threads.front();
+    auto next_thread = std::move(waiting_threads.front());
     waiting_threads.erase(waiting_threads.begin());
 
     next_thread->ReleaseWaitObject(this);
@@ -74,13 +76,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
     // CTR-OS doesn't use generation 0, so skip straight to 1.
     if (next_generation >= (1 << 15)) next_generation = 1;
 
-    Handle handle = generation | (slot << 15);
-    if (obj->handle == INVALID_HANDLE)
-        obj->handle = handle;
-
     generations[slot] = generation;
     objects[slot] = std::move(obj);
 
+    Handle handle = generation | (slot << 15);
     return MakeResult<Handle>(handle);
 }
 
@@ -102,7 +101,7 @@ ResultCode HandleTable::Close(Handle handle) {
 
     objects[slot] = nullptr;
 
-    generations[generation] = next_free_slot;
+    generations[slot] = next_free_slot;
     next_free_slot = slot;
     return RESULT_SUCCESS;
 }

+ 11 - 10
src/core/hle/kernel/kernel.h

@@ -58,14 +58,12 @@ enum {
     DEFAULT_STACK_SIZE  = 0x4000,
 };
 
-class HandleTable;
-
 class Object : NonCopyable {
-    friend class HandleTable;
-    u32 handle = INVALID_HANDLE;
 public:
     virtual ~Object() {}
-    Handle GetHandle() const { return handle; }
+
+    /// Returns a unique identifier for the object. For debugging purposes only.
+    unsigned int GetObjectId() const { return object_id; }
 
     virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
     virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
@@ -101,7 +99,10 @@ private:
     friend void intrusive_ptr_add_ref(Object*);
     friend void intrusive_ptr_release(Object*);
 
+    static unsigned int next_object_id;
+
     unsigned int ref_count = 0;
+    unsigned int object_id = next_object_id++;
 };
 
 // Special functions used by boost::instrusive_ptr to do automatic ref-counting
@@ -135,25 +136,26 @@ public:
      * Add a thread to wait on this object
      * @param thread Pointer to thread to add
      */
-    void AddWaitingThread(Thread* thread);
+    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
      */
-    void RemoveWaitingThread(Thread* thead);
+    void RemoveWaitingThread(Thread* thread);
 
     /**
      * Wake up the next thread waiting on this object
      * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
      */
-    Thread* WakeupNextThread();
+    SharedPtr<Thread> WakeupNextThread();
 
     /// Wake up all threads waiting on this object
     void WakeupAllWaitingThreads();
 
 private:
-    std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available
+    /// Threads waiting for this object to become available
+    std::vector<SharedPtr<Thread>> waiting_threads;
 };
 
 /**
@@ -274,7 +276,6 @@ private:
 };
 
 extern HandleTable g_handle_table;
-extern SharedPtr<Thread> g_main_thread;
 
 /// The ID code of the currently running game
 /// TODO(Subv): This variable should not be here, 

+ 14 - 27
src/core/hle/kernel/mutex.cpp

@@ -5,6 +5,8 @@
 #include <map>
 #include <vector>
 
+#include <boost/range/algorithm_ext/erase.hpp>
+
 #include "common/common.h"
 
 #include "core/hle/kernel/kernel.h"
@@ -13,9 +15,6 @@
 
 namespace Kernel {
 
-typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
-static MutexMap g_mutex_held_locks;
-
 /**
  * Resumes a thread waiting for the specified mutex
  * @param mutex The mutex that some thread is waiting on
@@ -33,21 +32,17 @@ static void ResumeWaitingThread(Mutex* mutex) {
 }
 
 void ReleaseThreadMutexes(Thread* thread) {
-    auto locked_range = g_mutex_held_locks.equal_range(thread);
-    
-    // Release every mutex that the thread holds, and resume execution on the waiting threads
-    for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
-        ResumeWaitingThread(iter->second.get());
+    for (auto& mtx : thread->held_mutexes) {
+        ResumeWaitingThread(mtx.get());
     }
-
-    // Erase all the locks that this thread holds
-    g_mutex_held_locks.erase(thread);
+    thread->held_mutexes.clear();
 }
 
-ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
+Mutex::Mutex() {}
+Mutex::~Mutex() {}
+
+SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
     SharedPtr<Mutex> mutex(new Mutex);
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
 
     mutex->initial_locked = initial_locked;
     mutex->locked = false;
@@ -58,7 +53,7 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name)
     if (initial_locked)
         mutex->Acquire();
 
-    return MakeResult<SharedPtr<Mutex>>(mutex);
+    return mutex;
 }
 
 bool Mutex::ShouldWait() {
@@ -69,30 +64,22 @@ void Mutex::Acquire() {
     Acquire(GetCurrentThread());
 }
 
-void Mutex::Acquire(Thread* thread) {
+void Mutex::Acquire(SharedPtr<Thread> thread) {
     _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
     if (locked)
         return;
 
     locked = true;
 
-    g_mutex_held_locks.insert(std::make_pair(thread, this));
-    holding_thread = thread;
+    thread->held_mutexes.insert(this);
+    holding_thread = std::move(thread);
 }
 
 void Mutex::Release() {
     if (!locked)
         return;
 
-    auto locked_range = g_mutex_held_locks.equal_range(holding_thread);
-
-    for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
-        if (iter->second == this) {
-            g_mutex_held_locks.erase(iter);
-            break;
-        }
-    }
-
+    holding_thread->held_mutexes.erase(this);
     ResumeWaitingThread(this);
 }
 

+ 4 - 3
src/core/hle/kernel/mutex.h

@@ -22,7 +22,7 @@ public:
      * @param name Optional name of mutex
      * @return Pointer to new Mutex object
      */
-    static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown");
+    static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
 
     std::string GetTypeName() const override { return "Mutex"; }
     std::string GetName() const override { return name; }
@@ -43,11 +43,12 @@ public:
     * @param mutex Mutex that is to be acquired
     * @param thread Thread that will acquire the mutex
     */
-    void Acquire(Thread* thread);
+    void Acquire(SharedPtr<Thread> thread);
     void Release();
 
 private:
-    Mutex() = default;
+    Mutex();
+    ~Mutex() override;
 };
 
 /**

+ 3 - 2
src/core/hle/kernel/semaphore.cpp

@@ -10,6 +10,9 @@
 
 namespace Kernel {
 
+Semaphore::Semaphore() {}
+Semaphore::~Semaphore() {}
+
 ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
         std::string name) {
 
@@ -18,8 +21,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou
                           ErrorSummary::WrongArgument, ErrorLevel::Permanent);
 
     SharedPtr<Semaphore> semaphore(new Semaphore);
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
 
     // When the semaphore is created, some slots are reserved for other threads,
     // and the rest is reserved for the caller thread

+ 2 - 1
src/core/hle/kernel/semaphore.h

@@ -47,7 +47,8 @@ public:
     ResultVal<s32> Release(s32 release_count);
 
 private:
-    Semaphore() = default;
+    Semaphore();
+    ~Semaphore() override;
 };
 
 } // namespace

+ 13 - 0
src/core/hle/kernel/session.cpp

@@ -0,0 +1,13 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/session.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+Session::Session() {}
+Session::~Session() {}
+
+}

+ 4 - 0
src/core/hle/kernel/session.h

@@ -5,6 +5,7 @@
 #pragma once
 
 #include "core/hle/kernel/kernel.h"
+#include "core/mem_map.h"
 
 namespace Kernel {
 
@@ -43,6 +44,9 @@ inline static u32* GetCommandBuffer(const int offset=0) {
  */
 class Session : public WaitObject {
 public:
+    Session();
+    ~Session() override;
+
     std::string GetTypeName() const override { return "Session"; }
 
     static const HandleType HANDLE_TYPE = HandleType::Session;

+ 9 - 8
src/core/hle/kernel/shared_memory.cpp

@@ -9,22 +9,23 @@
 
 namespace Kernel {
 
-ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) {
-    SharedPtr<SharedMemory> shared_memory(new SharedMemory);
+SharedMemory::SharedMemory() {}
+SharedMemory::~SharedMemory() {}
 
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory));
+SharedPtr<SharedMemory> SharedMemory::Create(std::string name) {
+    SharedPtr<SharedMemory> shared_memory(new SharedMemory);
 
     shared_memory->name = std::move(name);
-    return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory));
+
+    return shared_memory;
 }
 
 ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
         MemoryPermission other_permissions) {
 
     if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
-        LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
-                GetHandle(), address);
+        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!",
+                GetObjectId(), address);
         // TODO: Verify error code with hardware
         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
                 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
@@ -41,7 +42,7 @@ ResultVal<u8*> SharedMemory::GetPointer(u32 offset) {
     if (base_address != 0)
         return MakeResult<u8*>(Memory::GetPointer(base_address + offset));
 
-    LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle());
+    LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId());
     // TODO(yuriks): Verify error code.
     return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
             ErrorSummary::InvalidState, ErrorLevel::Permanent);

+ 3 - 2
src/core/hle/kernel/shared_memory.h

@@ -29,7 +29,7 @@ public:
      * Creates a shared memory object
      * @param name Optional object name, used only for debugging purposes.
      */
-    static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown");
+    static SharedPtr<SharedMemory> Create(std::string name = "Unknown");
 
     std::string GetTypeName() const override { return "SharedMemory"; }
 
@@ -57,7 +57,8 @@ public:
     std::string name;                   ///< Name of shared memory object (optional)
 
 private:
-    SharedMemory() = default;
+    SharedMemory();
+    ~SharedMemory() override;
 };
 
 } // namespace

+ 25 - 28
src/core/hle/kernel/thread.cpp

@@ -4,7 +4,6 @@
 
 #include <algorithm>
 #include <list>
-#include <map>
 #include <vector>
 
 #include "common/common.h"
@@ -41,6 +40,9 @@ static Thread* current_thread;
 static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
 static u32 next_thread_id; ///< The next available thread id
 
+Thread::Thread() {}
+Thread::~Thread() {}
+
 Thread* GetCurrentThread() {
     return current_thread;
 }
@@ -108,6 +110,9 @@ void Thread::Stop(const char* reason) {
     WakeupAllWaitingThreads();
 
     // Stopped threads are never waiting.
+    for (auto& wait_object : wait_objects) {
+        wait_object->RemoveWaitingThread(this);
+    }
     wait_objects.clear();
     wait_address = 0;
 }
@@ -228,13 +233,15 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
 
 /// Event type for the thread wake up event
 static int ThreadWakeupEventType = -1;
+// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
+//               us to simply use a pool index or similar.
+static Kernel::HandleTable wakeup_callback_handle_table;
 
 /// Callback that will wake up the thread it was scheduled for
-static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
-    Handle handle = static_cast<Handle>(parameter);
-    SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle);
+static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
+    SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
     if (thread == nullptr) {
-        LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
+        LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", thread_handle);
         return;
     }
 
@@ -248,14 +255,13 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
 }
 
 
-void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) {
+void Thread::WakeAfterDelay(s64 nanoseconds) {
     // Don't schedule a wakeup if the thread wants to wait forever
     if (nanoseconds == -1)
         return;
-    _dbg_assert_(Kernel, thread != nullptr);
 
     u64 microseconds = nanoseconds / 1000;
-    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle());
+    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
 }
 
 void Thread::ReleaseWaitObject(WaitObject* wait_object) {
@@ -302,7 +308,7 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) {
 
 void Thread::ResumeFromWait() {
     // Cancel any outstanding wakeup events
-    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
+    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
 
     status &= ~THREADSTATUS_WAIT;
 
@@ -326,11 +332,11 @@ static void DebugThreadQueue() {
     if (!thread) {
         return;
     }
-    LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle());
+    LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId());
     for (auto& t : thread_list) {
         s32 priority = thread_ready_queue.contains(t.get());
         if (priority != -1) {
-            LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle());
+            LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId());
         }
     }
 }
@@ -362,14 +368,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
 
     SharedPtr<Thread> thread(new Thread);
 
-    // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
-    //               the time being. Create a handle here, it will be copied to the handle field in
-    //               the object and use by the rest of the code. This should be removed when other
-    //               code doesn't rely on the handle anymore.
-    ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread);
-    if (handle.Failed())
-        return handle.Code();
-
     thread_list.push_back(thread);
     thread_ready_queue.prepare(priority);
 
@@ -385,6 +383,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
     thread->wait_objects.clear();
     thread->wait_address = 0;
     thread->name = std::move(name);
+    thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
 
     ResetThread(thread.get(), arg, 0);
     CallThread(thread.get());
@@ -418,16 +417,14 @@ void Thread::SetPriority(s32 priority) {
     }
 }
 
-Handle SetupIdleThread() {
+SharedPtr<Thread> SetupIdleThread() {
     // We need to pass a few valid values to get around parameter checking in Thread::Create.
-    auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
-            THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE);
-    _dbg_assert_(Kernel, thread_res.Succeeded());
-    SharedPtr<Thread> thread = std::move(*thread_res);
+    auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
+            THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE).MoveFrom();
 
     thread->idle = true;
     CallThread(thread.get());
-    return thread->GetHandle();
+    return thread;
 }
 
 SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) {
@@ -460,13 +457,13 @@ void Reschedule() {
     HLE::g_reschedule = false;
 
     if (next != nullptr) {
-        LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
+        LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId());
         SwitchContext(next);
     } else {
-        LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
+        LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId());
 
         for (auto& thread : thread_list) {
-            LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), 
+            LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), 
                       thread->current_priority, thread->status);
         }
     }

+ 21 - 10
src/core/hle/kernel/thread.h

@@ -7,6 +7,8 @@
 #include <string>
 #include <vector>
 
+#include <boost/container/flat_set.hpp>
+
 #include "common/common_types.h"
 
 #include "core/core.h"
@@ -40,6 +42,8 @@ enum ThreadStatus {
 
 namespace Kernel {
 
+class Mutex;
+
 class Thread final : public WaitObject {
 public:
     static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
@@ -77,6 +81,12 @@ public:
     /// Resumes a thread from waiting by marking it as "ready"
     void ResumeFromWait();
 
+    /**
+    * Schedules an event to wake up the specified thread after the specified delay.
+    * @param nanoseconds The time this thread will be allowed to sleep for.
+    */
+    void WakeAfterDelay(s64 nanoseconds);
+
     /**
      * Sets the result after the thread awakens (from either WaitSynchronization SVC)
      * @param result Value to set to the returned result
@@ -103,8 +113,10 @@ public:
 
     s32 processor_id;
 
-    std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
+    /// Mutexes currently held by this thread, which will be released when it exits.
+    boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
 
+    std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
     VAddr wait_address;     ///< If waiting on an AddressArbiter, this is the arbitration address
     bool wait_all;          ///< True if the thread is waiting on all objects before resuming
     bool wait_set_output;   ///< True if the output parameter should be set on thread wakeup
@@ -115,9 +127,15 @@ public:
     bool idle = false;
 
 private:
-    Thread() = default;
+    Thread();
+    ~Thread() override;
+
+    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
+    Handle callback_handle;
 };
 
+extern SharedPtr<Thread> g_main_thread;
+
 /// Sets up the primary application thread
 SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size);
 
@@ -150,20 +168,13 @@ void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bo
  */
 void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
 
-/**
- * Schedules an event to wake up the specified thread after the specified delay.
- * @param handle The thread handle.
- * @param nanoseconds The time this thread will be allowed to sleep for.
- */
-void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds);
-
 /**
  * Sets up the idle thread, this is a thread that is intended to never execute instructions,
  * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
  * and will try to yield on every call.
  * @returns The handle of the idle thread
  */
-Handle SetupIdleThread();
+SharedPtr<Thread> SetupIdleThread();
 
 /// Initialize threading
 void ThreadingInit();

+ 17 - 11
src/core/hle/kernel/timer.cpp

@@ -2,8 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <set>
-
 #include "common/common.h"
 
 #include "core/core_timing.h"
@@ -15,18 +13,24 @@ namespace Kernel {
 
 /// The event type of the generic timer callback event
 static int timer_callback_event_type = -1;
+// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
+//               us to simply use a pool index or similar.
+static Kernel::HandleTable timer_callback_handle_table;
+
+Timer::Timer() {}
+Timer::~Timer() {}
 
-ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) {
+SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
     SharedPtr<Timer> timer(new Timer);
-    // TOOD(yuriks): Don't create Handle (see Thread::Create())
-    CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer));
 
     timer->reset_type = reset_type;
     timer->signaled = false;
     timer->name = std::move(name);
     timer->initial_delay = 0;
     timer->interval_delay = 0;
-    return MakeResult<SharedPtr<Timer>>(timer);
+    timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
+
+    return timer;
 }
 
 bool Timer::ShouldWait() {
@@ -38,17 +42,19 @@ void Timer::Acquire() {
 }
 
 void Timer::Set(s64 initial, s64 interval) {
+    // Ensure we get rid of any previous scheduled event
+    Cancel();
+
     initial_delay = initial;
     interval_delay = interval;
 
     u64 initial_microseconds = initial / 1000;
-    // TODO(yuriks): Figure out a replacement for GetHandle here
-    CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
-            GetHandle());
+    CoreTiming::ScheduleEvent(usToCycles(initial_microseconds),
+            timer_callback_event_type, callback_handle);
 }
 
 void Timer::Cancel() {
-    CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle());
+    CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
 }
 
 void Timer::Clear() {
@@ -57,7 +63,7 @@ void Timer::Clear() {
 
 /// The timer callback event, called when a timer is fired
 static void TimerCallback(u64 timer_handle, int cycles_late) {
-    SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
+    SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle);
 
     if (timer == nullptr) {
         LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);

+ 6 - 2
src/core/hle/kernel/timer.h

@@ -19,7 +19,7 @@ public:
      * @param name Optional name of timer
      * @return The created Timer
      */
-    static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown");
+    static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
 
     std::string GetTypeName() const override { return "Timer"; }
     std::string GetName() const override { return name; }
@@ -49,7 +49,11 @@ public:
     void Clear();
 
 private:
-    Timer() = default;
+    Timer();
+    ~Timer() override;
+
+    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
+    Handle callback_handle;
 };
 
 /// Initializes the required variables for timers

+ 1 - 1
src/core/hle/service/ac_u.cpp

@@ -53,7 +53,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/act_u.cpp

@@ -18,7 +18,7 @@ namespace ACT_U {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/am_app.cpp

@@ -18,7 +18,7 @@ namespace AM_APP {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/am_net.cpp

@@ -38,7 +38,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/am_sys.cpp

@@ -18,7 +18,7 @@ namespace AM_SYS {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/apt_a.cpp

@@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/apt_s.cpp

@@ -117,7 +117,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 5 - 5
src/core/hle/service/apt_u.cpp

@@ -69,8 +69,8 @@ void Initialize(Service::Interface* self) {
     u32* cmd_buff = Kernel::GetCommandBuffer();
 
     // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
-    notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom();
-    pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom();
+    notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
+    pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause");
 
     cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
     cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom();
@@ -512,15 +512,15 @@ Interface::Interface() {
         file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
 
         // Create shared font memory object
-        shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom();
+        shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem");
     } else {
         LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
         shared_font_mem = nullptr;
     }
 
-    lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom();
+    lock = Kernel::Mutex::Create(false, "APT_U:Lock");
 
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/boss_p.cpp

@@ -18,7 +18,7 @@ namespace BOSS_P {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/boss_u.cpp

@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/cam_u.cpp

@@ -18,7 +18,7 @@ namespace CAM_U {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
     
 } // namespace

+ 1 - 1
src/core/hle/service/cecd_s.cpp

@@ -18,7 +18,7 @@ namespace CECD_S {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/cecd_u.cpp

@@ -18,7 +18,7 @@ namespace CECD_U {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/cfg/cfg_i.cpp

@@ -104,7 +104,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/cfg/cfg_s.cpp

@@ -92,7 +92,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/cfg/cfg_u.cpp

@@ -186,7 +186,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/csnd_snd.cpp

@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 2 - 3
src/core/hle/service/dsp_dsp.cpp

@@ -201,12 +201,11 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT,
-            "DSP_DSP::semaphore_event").MoveFrom();
+    semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
     interrupt_event = nullptr;
     read_pipe_count = 0;
 
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/err_f.cpp

@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/frd_a.cpp

@@ -18,7 +18,7 @@ namespace FRD_A {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/frd_u.cpp

@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 9 - 17
src/core/hle/service/fs/archive.cpp

@@ -163,7 +163,7 @@ public:
         case FileCommand::OpenLinkFile:
         {
             LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
-            cmd_buff[3] = GetHandle();
+            cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
             break;
         }
 
@@ -303,7 +303,8 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
     return RESULT_SUCCESS;
 }
 
-ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
+        const FileSys::Path& path, const FileSys::Mode mode) {
     Archive* archive = GetArchive(archive_handle);
     if (archive == nullptr)
         return ERR_INVALID_HANDLE;
@@ -314,10 +315,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
                           ErrorSummary::NotFound, ErrorLevel::Status);
     }
 
-    auto file = Common::make_unique<File>(std::move(backend), path);
-    // TOOD(yuriks): Fix error reporting
-    Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
-    return MakeResult<Handle>(handle);
+    auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path));
+    return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file));
 }
 
 ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
@@ -403,13 +402,8 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
                       ErrorSummary::NothingHappened, ErrorLevel::Status);
 }
 
-/**
- * Open a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Opened Directory object
- */
-ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
+        const FileSys::Path& path) {
     Archive* archive = GetArchive(archive_handle);
     if (archive == nullptr)
         return ERR_INVALID_HANDLE;
@@ -420,10 +414,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
                           ErrorSummary::NotFound, ErrorLevel::Permanent);
     }
 
-    auto directory = Common::make_unique<Directory>(std::move(backend), path);
-    // TOOD(yuriks): Fix error reporting
-    Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
-    return MakeResult<Handle>(handle);
+    auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
+    return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory));
 }
 
 ResultCode FormatSaveData() {

+ 10 - 4
src/core/hle/service/fs/archive.h

@@ -15,6 +15,10 @@ extern const std::string SYSTEM_ID;
 /// The scrambled SD card CID, also known as ID1
 extern const std::string SDCARD_ID;
 
+namespace Kernel {
+    class Session;
+}
+
 namespace Service {
 namespace FS {
 
@@ -58,9 +62,10 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
  * @param archive_handle Handle to an open Archive object
  * @param path Path to the File inside of the Archive
  * @param mode Mode under which to open the File
- * @return Handle to the opened File object
+ * @return The opened File object as a Session
  */
-ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode);
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
+        const FileSys::Path& path, const FileSys::Mode mode);
 
 /**
  * Delete a File from an Archive
@@ -121,9 +126,10 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
  * Open a Directory from an Archive
  * @param archive_handle Handle to an open Archive object
  * @param path Path to the Directory inside of the Archive
- * @return Handle to the opened File object
+ * @return The opened Directory object as a Session
  */
-ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
+        const FileSys::Path& path);
 
 /**
  * Creates a blank SaveData archive.

+ 16 - 13
src/core/hle/service/fs/fs_user.cpp

@@ -14,6 +14,9 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Namespace FS_User
 
+using Kernel::SharedPtr;
+using Kernel::Session;
+
 namespace Service {
 namespace FS {
 
@@ -58,10 +61,10 @@ static void OpenFile(Service::Interface* self) {
 
     LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
 
-    ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode);
-    cmd_buff[1] = handle.Code().raw;
-    if (handle.Succeeded()) {
-        cmd_buff[3] = *handle;
+    ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
+    cmd_buff[1] = file_res.Code().raw;
+    if (file_res.Succeeded()) {
+        cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
     } else {
         cmd_buff[3] = 0;
         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -114,10 +117,10 @@ static void OpenFileDirectly(Service::Interface* self) {
     }
     SCOPE_EXIT({ CloseArchive(*archive_handle); });
 
-    ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode);
-    cmd_buff[1] = handle.Code().raw;
-    if (handle.Succeeded()) {
-        cmd_buff[3] = *handle;
+    ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode);
+    cmd_buff[1] = file_res.Code().raw;
+    if (file_res.Succeeded()) {
+        cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
     } else {
         cmd_buff[3] = 0;
         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -334,10 +337,10 @@ static void OpenDirectory(Service::Interface* self) {
 
     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
 
-    ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path);
-    cmd_buff[1] = handle.Code().raw;
-    if (handle.Succeeded()) {
-        cmd_buff[3] = *handle;
+    ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
+    cmd_buff[1] = dir_res.Code().raw;
+    if (dir_res.Succeeded()) {
+        cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom();
     } else {
         LOG_ERROR(Service_FS, "failed to get a handle for directory");
     }
@@ -588,7 +591,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 FSUserInterface::FSUserInterface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace FS

+ 2 - 2
src/core/hle/service/gsp_gpu.cpp

@@ -187,7 +187,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
 
     g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
     _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!");
-    g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom();
+    g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem");
 
     Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
 
@@ -389,7 +389,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 
     g_interrupt_event = 0;
     g_shared_memory = 0;

+ 1 - 1
src/core/hle/service/gsp_lcd.cpp

@@ -20,7 +20,7 @@ namespace GSP_LCD {
 // Interface class
 
 Interface::Interface() {
-    //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    //Register(FunctionTable);
 }
 
 } // namespace

+ 8 - 6
src/core/hle/service/hid/hid.cpp

@@ -30,6 +30,8 @@ static s16 next_circle_y = 0;
  * Gets a pointer to the PadData structure inside HID shared memory
  */
 static inline PadData* GetPadData() {
+    if (g_shared_mem == nullptr)
+        return nullptr;
     return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr));
 }
 
@@ -122,14 +124,14 @@ void PadUpdateComplete() {
 void HIDInit() {
     using namespace Kernel;
 
-    g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom();
+    g_shared_mem = SharedMemory::Create("HID:SharedMem");
 
     // Create event handles
-    g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom();
-    g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom();
-    g_event_accelerometer  = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom();
-    g_event_gyroscope      = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom();
-    g_event_debug_pad      = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom();
+    g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1");
+    g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2");
+    g_event_accelerometer  = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer");
+    g_event_gyroscope      = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope");
+    g_event_debug_pad      = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad");
 }
 
 void HIDShutdown() {

+ 1 - 1
src/core/hle/service/hid/hid_spvr.cpp

@@ -32,7 +32,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
     
 } // namespace

+ 1 - 1
src/core/hle/service/hid/hid_user.cpp

@@ -72,7 +72,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/http_c.cpp

@@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ir_rst.cpp

@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ir_u.cpp

@@ -36,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ldr_ro.cpp

@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/mic_u.cpp

@@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ndm_u.cpp

@@ -24,7 +24,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/news_s.cpp

@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/news_u.cpp

@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/nim_aoc.cpp

@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ns_s.cpp

@@ -21,7 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/nwm_uds.cpp

@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/pm_app.cpp

@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ptm_play.cpp

@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
     
 } // namespace

+ 1 - 1
src/core/hle/service/ptm_sysm.cpp

@@ -50,7 +50,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ptm_u.cpp

@@ -137,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
     // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file
     // TODO(Subv): In the future we should use the FS service to query this archive
     std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);

+ 55 - 75
src/core/hle/service/service.cpp

@@ -54,96 +54,76 @@
 
 namespace Service {
 
-Manager* g_manager = nullptr;  ///< Service manager
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-// Service Manager class
-
-void Manager::AddService(Interface* service) {
-    // TOOD(yuriks): Fix error reporting
-    m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
-    m_services.push_back(service);
-}
-
-void Manager::DeleteService(const std::string& port_name) {
-    Interface* service = FetchFromPortName(port_name);
-    m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end());
-    m_port_map.erase(port_name);
-}
+// Module interface
 
-Interface* Manager::FetchFromHandle(Handle handle) {
-    // TODO(yuriks): This function is very suspicious and should probably be exterminated.
-    return Kernel::g_handle_table.Get<Interface>(handle).get();
+static void AddNamedPort(Interface* interface) {
+    g_kernel_named_ports.emplace(interface->GetPortName(), interface);
 }
 
-Interface* Manager::FetchFromPortName(const std::string& port_name) {
-    auto itr = m_port_map.find(port_name);
-    if (itr == m_port_map.end()) {
-        return nullptr;
-    }
-    return FetchFromHandle(itr->second);
+static void AddService(Interface* interface) {
+    g_srv_services.emplace(interface->GetPortName(), interface);
 }
 
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Module interface
-
 /// Initialize ServiceManager
 void Init() {
-    g_manager = new Manager;
-
-    g_manager->AddService(new SRV::Interface);
-    g_manager->AddService(new AC_U::Interface);
-    g_manager->AddService(new ACT_U::Interface);
-    g_manager->AddService(new AM_APP::Interface);
-    g_manager->AddService(new AM_NET::Interface);
-    g_manager->AddService(new AM_SYS::Interface);
-    g_manager->AddService(new APT_A::Interface);
-    g_manager->AddService(new APT_S::Interface);
-    g_manager->AddService(new APT_U::Interface);
-    g_manager->AddService(new BOSS_P::Interface);
-    g_manager->AddService(new BOSS_U::Interface);
-    g_manager->AddService(new CAM_U::Interface);
-    g_manager->AddService(new CECD_S::Interface);
-    g_manager->AddService(new CECD_U::Interface);
-    g_manager->AddService(new CFG_I::Interface);
-    g_manager->AddService(new CFG_S::Interface);
-    g_manager->AddService(new CFG_U::Interface);
-    g_manager->AddService(new CSND_SND::Interface);
-    g_manager->AddService(new DSP_DSP::Interface);
-    g_manager->AddService(new ERR_F::Interface);
-    g_manager->AddService(new FRD_A::Interface);
-    g_manager->AddService(new FRD_U::Interface);
-    g_manager->AddService(new FS::FSUserInterface);
-    g_manager->AddService(new GSP_GPU::Interface);
-    g_manager->AddService(new GSP_LCD::Interface);
-    g_manager->AddService(new HID_User::Interface);
-    g_manager->AddService(new HID_SPVR::Interface);
-    g_manager->AddService(new HTTP_C::Interface);
-    g_manager->AddService(new IR_RST::Interface);
-    g_manager->AddService(new IR_U::Interface);
-    g_manager->AddService(new LDR_RO::Interface);
-    g_manager->AddService(new MIC_U::Interface);
-    g_manager->AddService(new NDM_U::Interface);
-    g_manager->AddService(new NEWS_S::Interface);
-    g_manager->AddService(new NEWS_U::Interface);
-    g_manager->AddService(new NIM_AOC::Interface);
-    g_manager->AddService(new NS_S::Interface);
-    g_manager->AddService(new NWM_UDS::Interface);
-    g_manager->AddService(new PM_APP::Interface);
-    g_manager->AddService(new PTM_PLAY::Interface);
-    g_manager->AddService(new PTM_U::Interface);
-    g_manager->AddService(new PTM_SYSM::Interface);
-    g_manager->AddService(new SOC_U::Interface);
-    g_manager->AddService(new SSL_C::Interface);
-    g_manager->AddService(new Y2R_U::Interface);
+    AddNamedPort(new SRV::Interface);
+
+    AddService(new AC_U::Interface);
+    AddService(new ACT_U::Interface);
+    AddService(new AM_APP::Interface);
+    AddService(new AM_NET::Interface);
+    AddService(new AM_SYS::Interface);
+    AddService(new APT_A::Interface);
+    AddService(new APT_S::Interface);
+    AddService(new APT_U::Interface);
+    AddService(new BOSS_P::Interface);
+    AddService(new BOSS_U::Interface);
+    AddService(new CAM_U::Interface);
+    AddService(new CECD_S::Interface);
+    AddService(new CECD_U::Interface);
+    AddService(new CFG_I::Interface);
+    AddService(new CFG_S::Interface);
+    AddService(new CFG_U::Interface);
+    AddService(new CSND_SND::Interface);
+    AddService(new DSP_DSP::Interface);
+    AddService(new ERR_F::Interface);
+    AddService(new FRD_A::Interface);
+    AddService(new FRD_U::Interface);
+    AddService(new FS::FSUserInterface);
+    AddService(new GSP_GPU::Interface);
+    AddService(new GSP_LCD::Interface);
+    AddService(new HID_User::Interface);
+    AddService(new HID_SPVR::Interface);
+    AddService(new HTTP_C::Interface);
+    AddService(new IR_RST::Interface);
+    AddService(new IR_U::Interface);
+    AddService(new LDR_RO::Interface);
+    AddService(new MIC_U::Interface);
+    AddService(new NDM_U::Interface);
+    AddService(new NEWS_S::Interface);
+    AddService(new NEWS_U::Interface);
+    AddService(new NIM_AOC::Interface);
+    AddService(new NS_S::Interface);
+    AddService(new NWM_UDS::Interface);
+    AddService(new PM_APP::Interface);
+    AddService(new PTM_PLAY::Interface);
+    AddService(new PTM_U::Interface);
+    AddService(new PTM_SYSM::Interface);
+    AddService(new SOC_U::Interface);
+    AddService(new SSL_C::Interface);
+    AddService(new Y2R_U::Interface);
 
     LOG_DEBUG(Service, "initialized OK");
 }
 
 /// Shutdown ServiceManager
 void Shutdown() {
-    delete g_manager;
+    g_srv_services.clear();
+    g_kernel_named_ports.clear();
     LOG_DEBUG(Service, "shutdown OK");
 }
 

+ 21 - 52
src/core/hle/service/service.h

@@ -5,9 +5,11 @@
 #pragma once
 
 #include <algorithm>
-#include <vector>
-#include <map>
 #include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <boost/container/flat_map.hpp>
 
 #include "common/common.h"
 #include "common/string_util.h"
@@ -27,7 +29,7 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character
 class Manager;
 
 /// Interface to a CTROS service
-class Interface  : public Kernel::Session {
+class Interface : public Kernel::Session {
     // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
     // just something that encapsulates a session and acts as a helper to implement service
     // processes.
@@ -38,11 +40,11 @@ class Interface  : public Kernel::Session {
      * Creates a function string for logging, complete with the name (or header code, depending 
      * on what's passed in) the port name, and all the cmd_buff arguments.
      */
-    std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) {
+    std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
         // Number of params == bits 0-5 + bits 6-11
         int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
 
-        std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str());
+        std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
         for (int i = 1; i <= num_params; ++i) {
             function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
         }
@@ -57,7 +59,7 @@ public:
     struct FunctionInfo {
         u32         id;
         Function    func;
-        std::string name;
+        const char* name;
     };
 
     /**
@@ -68,34 +70,19 @@ public:
         return "[UNKNOWN SERVICE PORT]";
     }
 
-    /// Allocates a new handle for the service
-    Handle CreateHandle(Kernel::Object *obj) {
-        // TODO(yuriks): Fix error reporting
-        Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
-        m_handles.push_back(handle);
-        return handle;
-    }
-
-    /// Frees a handle from the service
-    template <class T>
-    void DeleteHandle(const Handle handle) {
-        Kernel::g_handle_table.Close(handle);
-        m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
-    }
-
     ResultVal<bool> SyncRequest() override {
         u32* cmd_buff = Kernel::GetCommandBuffer();
         auto itr = m_functions.find(cmd_buff[0]);
 
         if (itr == m_functions.end() || itr->second.func == nullptr) {
             std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
-            LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str());
+            LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
 
             // TODO(bunnei): Hack - ignore error
             cmd_buff[1] = 0;
             return MakeResult<bool>(false);
         } else {
-            LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str());
+            LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
         }
 
         itr->second.func(this);
@@ -108,37 +95,18 @@ protected:
     /**
      * Registers the functions in the service
      */
-    void Register(const FunctionInfo* functions, int len) {
-        for (int i = 0; i < len; i++) {
-            m_functions[functions[i].id] = functions[i];
+    template <size_t N>
+    void Register(const FunctionInfo (&functions)[N]) {
+        m_functions.reserve(N);
+        for (auto& fn : functions) {
+            // Usually this array is sorted by id already, so hint to instead at the end
+            m_functions.emplace_hint(m_functions.cend(), fn.id, fn);
         }
     }
 
 private:
+    boost::container::flat_map<u32, FunctionInfo> m_functions;
 
-    std::vector<Handle>         m_handles;
-    std::map<u32, FunctionInfo> m_functions;
-
-};
-
-/// Simple class to manage accessing services from ports and UID handles
-class Manager {
-public:
-    /// Add a service to the manager
-    void AddService(Interface* service);
-
-    /// Removes a service from the manager
-    void DeleteService(const std::string& port_name);
-
-    /// Get a Service Interface from its Handle
-    Interface* FetchFromHandle(Handle handle);
-
-    /// Get a Service Interface from its port
-    Interface* FetchFromPortName(const std::string& port_name);
-
-private:
-    std::vector<Interface*>     m_services;
-    std::map<std::string, u32>  m_port_map;
 };
 
 /// Initialize ServiceManager
@@ -147,8 +115,9 @@ void Init();
 /// Shutdown ServiceManager
 void Shutdown();
 
-
-extern Manager* g_manager; ///< Service manager
-
+/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
 
 } // namespace

+ 1 - 1
src/core/hle/service/soc_u.cpp

@@ -734,7 +734,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 Interface::~Interface() {

+ 5 - 5
src/core/hle/service/srv.cpp

@@ -23,7 +23,7 @@ static void GetProcSemaphore(Service::Interface* self) {
     u32* cmd_buff = Kernel::GetCommandBuffer();
 
     // TODO(bunnei): Change to a semaphore once these have been implemented
-    event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom();
+    event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event");
     event_handle->Clear();
 
     cmd_buff[1] = 0; // No error
@@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) {
     u32* cmd_buff = Kernel::GetCommandBuffer();
 
     std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
-    Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
+    auto it = Service::g_srv_services.find(port_name);
 
-    if (nullptr != service) {
-        cmd_buff[3] = service->GetHandle();
+    if (it != Service::g_srv_services.end()) {
+        cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom();
         LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
     } else {
         LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
@@ -63,7 +63,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/ssl_c.cpp

@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
 
 } // namespace

+ 1 - 1
src/core/hle/service/y2r_u.cpp

@@ -54,7 +54,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 // Interface class
 
 Interface::Interface() {
-    Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+    Register(FunctionTable);
 }
     
 } // namespace

+ 35 - 23
src/core/hle/svc.cpp

@@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE;
 
 namespace SVC {
 
+const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
+        ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
+const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
+        ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
+
 /// An invalid result code that is meant to be overwritten when a thread resumes from waiting
 const ResultCode RESULT_INVALID(0xDEADC0DE);
 
@@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
 }
 
 /// Connect to an OS service given the port name, returns the handle to the port to out
-static ResultCode ConnectToPort(Handle* out, const char* port_name) {
-    Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
+static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
+    if (port_name == nullptr)
+        return ERR_NOT_FOUND;
+    if (std::strlen(port_name) > 11)
+        return ERR_PORT_NAME_TOO_LONG;
 
     LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
-    _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
 
-    *out = service->GetHandle();
+    auto it = Service::g_kernel_named_ports.find(port_name);
+    if (it == Service::g_kernel_named_ports.end()) {
+        LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name);
+        return ERR_NOT_FOUND;
+    }
 
+    CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second));
     return RESULT_SUCCESS;
 }
 
@@ -119,9 +131,8 @@ static ResultCode SendSyncRequest(Handle handle) {
 
 /// Close a handle
 static ResultCode CloseHandle(Handle handle) {
-    // ImplementMe
-    LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
-    return RESULT_SUCCESS;
+    LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
+    return Kernel::g_handle_table.Close(handle);
 }
 
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
@@ -140,7 +151,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
         Kernel::WaitCurrentThread_WaitSynchronization(object, false, false);
 
         // Create an event to wake the thread up after the specified nanosecond delay has passed
-        Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds);
+        Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
 
         HLE::Reschedule(__func__);
 
@@ -216,7 +227,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
         }
 
         // Create an event to wake the thread up after the specified nanosecond delay has passed
-        Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds);
+        Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
 
         HLE::Reschedule(__func__);
 
@@ -250,7 +261,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
 static ResultCode CreateAddressArbiter(Handle* out_handle) {
     using Kernel::AddressArbiter;
 
-    CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create());
+    SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create();
     CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter)));
     LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle);
     return RESULT_SUCCESS;
@@ -355,7 +366,7 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) {
 static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
     using Kernel::Mutex;
 
-    CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0));
+    SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
     CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
 
     LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
@@ -423,7 +434,9 @@ static ResultCode QueryMemory(void* info, void* out, u32 addr) {
 
 /// Create an event
 static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
-    CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type)));
+    using Kernel::Event;
+
+    SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type));
     CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
 
     LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
@@ -433,19 +446,17 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
 
 /// Duplicates a kernel handle
 static ResultCode DuplicateHandle(Handle* out, Handle handle) {
-    ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
-    if (out_h.Succeeded()) {
-        *out = *out_h;
-        LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
-    }
-    return out_h.Code();
+    CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle));
+    LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
+    return RESULT_SUCCESS;
 }
 
 /// Signals an event
 static ResultCode SignalEvent(Handle handle) {
+    using Kernel::Event;
     LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
 
-    auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
+    SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
     if (evt == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -456,9 +467,10 @@ static ResultCode SignalEvent(Handle handle) {
 
 /// Clears an event
 static ResultCode ClearEvent(Handle handle) {
+    using Kernel::Event;
     LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
 
-    auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
+    SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
     if (evt == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -470,7 +482,7 @@ static ResultCode ClearEvent(Handle handle) {
 static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
     using Kernel::Timer;
 
-    CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type)));
+    SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type));
     CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
 
     LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
@@ -528,7 +540,7 @@ static void SleepThread(s64 nanoseconds) {
     Kernel::WaitCurrentThread_Sleep();
 
     // Create an event to wake the thread up after the specified nanosecond delay has passed
-    Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds);
+    Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds);
 
     HLE::Reschedule(__func__);
 }
@@ -544,7 +556,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
     using Kernel::SharedMemory;
     // TODO(Subv): Implement this function
 
-    CASCADE_RESULT(auto shared_memory, SharedMemory::Create());
+    SharedPtr<SharedMemory> shared_memory = SharedMemory::Create();
     CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
 
     LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);