summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2015-02-02 13:04:04 -0500
committerGravatar bunnei2015-02-02 13:04:04 -0500
commit7f730ed158bc9bba064100b9644b318134ef0bb3 (patch)
treec4181a69ff882e1af1b7d65bf3596a6cb3dd88b9 /src
parentMerge pull request #517 from bunnei/blend-factors (diff)
parentKernel: Stop creating useless Handles during object creation (diff)
downloadyuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.tar.gz
yuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.tar.xz
yuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.zip
Merge pull request #523 from yuriks/kernel-lifetime5
Kernel Lifetime Reform Pt. 5: The Reckoning
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp13
-rw-r--r--src/core/hle/kernel/address_arbiter.h5
-rw-r--r--src/core/hle/kernel/event.cpp9
-rw-r--r--src/core/hle/kernel/event.h5
-rw-r--r--src/core/hle/kernel/kernel.cpp17
-rw-r--r--src/core/hle/kernel/kernel.h21
-rw-r--r--src/core/hle/kernel/mutex.cpp41
-rw-r--r--src/core/hle/kernel/mutex.h7
-rw-r--r--src/core/hle/kernel/semaphore.cpp5
-rw-r--r--src/core/hle/kernel/semaphore.h3
-rw-r--r--src/core/hle/kernel/session.cpp13
-rw-r--r--src/core/hle/kernel/session.h4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp17
-rw-r--r--src/core/hle/kernel/shared_memory.h5
-rw-r--r--src/core/hle/kernel/thread.cpp53
-rw-r--r--src/core/hle/kernel/thread.h31
-rw-r--r--src/core/hle/kernel/timer.cpp28
-rw-r--r--src/core/hle/kernel/timer.h8
-rw-r--r--src/core/hle/service/ac_u.cpp2
-rw-r--r--src/core/hle/service/act_u.cpp2
-rw-r--r--src/core/hle/service/am_app.cpp2
-rw-r--r--src/core/hle/service/am_net.cpp2
-rw-r--r--src/core/hle/service/am_sys.cpp2
-rw-r--r--src/core/hle/service/apt_a.cpp2
-rw-r--r--src/core/hle/service/apt_s.cpp2
-rw-r--r--src/core/hle/service/apt_u.cpp10
-rw-r--r--src/core/hle/service/boss_p.cpp2
-rw-r--r--src/core/hle/service/boss_u.cpp2
-rw-r--r--src/core/hle/service/cam_u.cpp2
-rw-r--r--src/core/hle/service/cecd_s.cpp2
-rw-r--r--src/core/hle/service/cecd_u.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp2
-rw-r--r--src/core/hle/service/csnd_snd.cpp2
-rw-r--r--src/core/hle/service/dsp_dsp.cpp5
-rw-r--r--src/core/hle/service/err_f.cpp2
-rw-r--r--src/core/hle/service/frd_a.cpp2
-rw-r--r--src/core/hle/service/frd_u.cpp2
-rw-r--r--src/core/hle/service/fs/archive.cpp26
-rw-r--r--src/core/hle/service/fs/archive.h14
-rw-r--r--src/core/hle/service/fs/fs_user.cpp29
-rw-r--r--src/core/hle/service/gsp_gpu.cpp4
-rw-r--r--src/core/hle/service/gsp_lcd.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp14
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp2
-rw-r--r--src/core/hle/service/hid/hid_user.cpp2
-rw-r--r--src/core/hle/service/http_c.cpp2
-rw-r--r--src/core/hle/service/ir_rst.cpp2
-rw-r--r--src/core/hle/service/ir_u.cpp2
-rw-r--r--src/core/hle/service/ldr_ro.cpp2
-rw-r--r--src/core/hle/service/mic_u.cpp2
-rw-r--r--src/core/hle/service/ndm_u.cpp2
-rw-r--r--src/core/hle/service/news_s.cpp2
-rw-r--r--src/core/hle/service/news_u.cpp2
-rw-r--r--src/core/hle/service/nim_aoc.cpp2
-rw-r--r--src/core/hle/service/ns_s.cpp2
-rw-r--r--src/core/hle/service/nwm_uds.cpp2
-rw-r--r--src/core/hle/service/pm_app.cpp2
-rw-r--r--src/core/hle/service/ptm_play.cpp2
-rw-r--r--src/core/hle/service/ptm_sysm.cpp2
-rw-r--r--src/core/hle/service/ptm_u.cpp2
-rw-r--r--src/core/hle/service/service.cpp130
-rw-r--r--src/core/hle/service/service.h73
-rw-r--r--src/core/hle/service/soc_u.cpp2
-rw-r--r--src/core/hle/service/srv.cpp10
-rw-r--r--src/core/hle/service/ssl_c.cpp2
-rw-r--r--src/core/hle/service/y2r_u.cpp2
-rw-r--r--src/core/hle/svc.cpp58
70 files changed, 367 insertions, 372 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ac173c486..0ab0e440c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -26,6 +26,7 @@ set(SRCS
26 hle/kernel/kernel.cpp 26 hle/kernel/kernel.cpp
27 hle/kernel/mutex.cpp 27 hle/kernel/mutex.cpp
28 hle/kernel/semaphore.cpp 28 hle/kernel/semaphore.cpp
29 hle/kernel/session.cpp
29 hle/kernel/shared_memory.cpp 30 hle/kernel/shared_memory.cpp
30 hle/kernel/timer.cpp 31 hle/kernel/timer.cpp
31 hle/kernel/thread.cpp 32 hle/kernel/thread.cpp
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 2d01e2ef5..42f8ce2d9 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -15,14 +15,15 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) { 18AddressArbiter::AddressArbiter() {}
19AddressArbiter::~AddressArbiter() {}
20
21SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
19 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); 22 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
20 // TOOD(yuriks): Don't create Handle (see Thread::Create())
21 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter));
22 23
23 address_arbiter->name = std::move(name); 24 address_arbiter->name = std::move(name);
24 25
25 return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter)); 26 return address_arbiter;
26} 27}
27 28
28ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 29ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
@@ -51,7 +52,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
51 case ArbitrationType::WaitIfLessThanWithTimeout: 52 case ArbitrationType::WaitIfLessThanWithTimeout:
52 if ((s32)Memory::Read32(address) <= value) { 53 if ((s32)Memory::Read32(address) <= value) {
53 Kernel::WaitCurrentThread_ArbitrateAddress(address); 54 Kernel::WaitCurrentThread_ArbitrateAddress(address);
54 Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); 55 GetCurrentThread()->WakeAfterDelay(nanoseconds);
55 HLE::Reschedule(__func__); 56 HLE::Reschedule(__func__);
56 } 57 }
57 break; 58 break;
@@ -71,7 +72,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
71 Memory::Write32(address, memory_value); 72 Memory::Write32(address, memory_value);
72 if (memory_value <= value) { 73 if (memory_value <= value) {
73 Kernel::WaitCurrentThread_ArbitrateAddress(address); 74 Kernel::WaitCurrentThread_ArbitrateAddress(address);
74 Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); 75 GetCurrentThread()->WakeAfterDelay(nanoseconds);
75 HLE::Reschedule(__func__); 76 HLE::Reschedule(__func__);
76 } 77 }
77 break; 78 break;
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 638afff9e..8f6a1a8df 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -34,7 +34,7 @@ public:
34 * @param name Optional name used for debugging. 34 * @param name Optional name used for debugging.
35 * @returns The created AddressArbiter. 35 * @returns The created AddressArbiter.
36 */ 36 */
37 static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown"); 37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 38
39 std::string GetTypeName() const override { return "Arbiter"; } 39 std::string GetTypeName() const override { return "Arbiter"; }
40 std::string GetName() const override { return name; } 40 std::string GetName() const override { return name; }
@@ -47,7 +47,8 @@ public:
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 48
49private: 49private:
50 AddressArbiter() = default; 50 AddressArbiter();
51 ~AddressArbiter() override;
51}; 52};
52 53
53} // namespace FileSys 54} // namespace FileSys
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index d9ad40c6a..898e1c98f 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -14,16 +14,17 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) { 17Event::Event() {}
18Event::~Event() {}
19
20SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
18 SharedPtr<Event> evt(new Event); 21 SharedPtr<Event> evt(new Event);
19 // TOOD(yuriks): Don't create Handle (see Thread::Create())
20 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt));
21 22
22 evt->signaled = false; 23 evt->signaled = false;
23 evt->reset_type = evt->intitial_reset_type = reset_type; 24 evt->reset_type = evt->intitial_reset_type = reset_type;
24 evt->name = std::move(name); 25 evt->name = std::move(name);
25 26
26 return MakeResult<SharedPtr<Event>>(evt); 27 return evt;
27} 28}
28 29
29bool Event::ShouldWait() { 30bool Event::ShouldWait() {
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 2c3e6b14e..fba960d2a 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -18,7 +18,7 @@ public:
18 * @param reset_type ResetType describing how to create event 18 * @param reset_type ResetType describing how to create event
19 * @param name Optional name of event 19 * @param name Optional name of event
20 */ 20 */
21 static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown"); 21 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
22 22
23 std::string GetTypeName() const override { return "Event"; } 23 std::string GetTypeName() const override { return "Event"; }
24 std::string GetName() const override { return name; } 24 std::string GetName() const override { return name; }
@@ -39,7 +39,8 @@ public:
39 void Clear(); 39 void Clear();
40 40
41private: 41private:
42 Event() = default; 42 Event();
43 ~Event() override;
43}; 44};
44 45
45} // namespace 46} // namespace
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index d7fa4dcea..7e0b9542e 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -14,14 +14,16 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17unsigned int Object::next_object_id = 0;
18
17SharedPtr<Thread> g_main_thread = nullptr; 19SharedPtr<Thread> g_main_thread = nullptr;
18HandleTable g_handle_table; 20HandleTable g_handle_table;
19u64 g_program_id = 0; 21u64 g_program_id = 0;
20 22
21void WaitObject::AddWaitingThread(Thread* thread) { 23void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
22 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); 24 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
23 if (itr == waiting_threads.end()) 25 if (itr == waiting_threads.end())
24 waiting_threads.push_back(thread); 26 waiting_threads.push_back(std::move(thread));
25} 27}
26 28
27void WaitObject::RemoveWaitingThread(Thread* thread) { 29void WaitObject::RemoveWaitingThread(Thread* thread) {
@@ -30,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
30 waiting_threads.erase(itr); 32 waiting_threads.erase(itr);
31} 33}
32 34
33Thread* WaitObject::WakeupNextThread() { 35SharedPtr<Thread> WaitObject::WakeupNextThread() {
34 if (waiting_threads.empty()) 36 if (waiting_threads.empty())
35 return nullptr; 37 return nullptr;
36 38
37 auto next_thread = waiting_threads.front(); 39 auto next_thread = std::move(waiting_threads.front());
38 waiting_threads.erase(waiting_threads.begin()); 40 waiting_threads.erase(waiting_threads.begin());
39 41
40 next_thread->ReleaseWaitObject(this); 42 next_thread->ReleaseWaitObject(this);
@@ -74,13 +76,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
74 // CTR-OS doesn't use generation 0, so skip straight to 1. 76 // CTR-OS doesn't use generation 0, so skip straight to 1.
75 if (next_generation >= (1 << 15)) next_generation = 1; 77 if (next_generation >= (1 << 15)) next_generation = 1;
76 78
77 Handle handle = generation | (slot << 15);
78 if (obj->handle == INVALID_HANDLE)
79 obj->handle = handle;
80
81 generations[slot] = generation; 79 generations[slot] = generation;
82 objects[slot] = std::move(obj); 80 objects[slot] = std::move(obj);
83 81
82 Handle handle = generation | (slot << 15);
84 return MakeResult<Handle>(handle); 83 return MakeResult<Handle>(handle);
85} 84}
86 85
@@ -102,7 +101,7 @@ ResultCode HandleTable::Close(Handle handle) {
102 101
103 objects[slot] = nullptr; 102 objects[slot] = nullptr;
104 103
105 generations[generation] = next_free_slot; 104 generations[slot] = next_free_slot;
106 next_free_slot = slot; 105 next_free_slot = slot;
107 return RESULT_SUCCESS; 106 return RESULT_SUCCESS;
108} 107}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 9860479ac..4d8e388b6 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -58,14 +58,12 @@ enum {
58 DEFAULT_STACK_SIZE = 0x4000, 58 DEFAULT_STACK_SIZE = 0x4000,
59}; 59};
60 60
61class HandleTable;
62
63class Object : NonCopyable { 61class Object : NonCopyable {
64 friend class HandleTable;
65 u32 handle = INVALID_HANDLE;
66public: 62public:
67 virtual ~Object() {} 63 virtual ~Object() {}
68 Handle GetHandle() const { return handle; } 64
65 /// Returns a unique identifier for the object. For debugging purposes only.
66 unsigned int GetObjectId() const { return object_id; }
69 67
70 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 68 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
71 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 69 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
@@ -101,7 +99,10 @@ private:
101 friend void intrusive_ptr_add_ref(Object*); 99 friend void intrusive_ptr_add_ref(Object*);
102 friend void intrusive_ptr_release(Object*); 100 friend void intrusive_ptr_release(Object*);
103 101
102 static unsigned int next_object_id;
103
104 unsigned int ref_count = 0; 104 unsigned int ref_count = 0;
105 unsigned int object_id = next_object_id++;
105}; 106};
106 107
107// Special functions used by boost::instrusive_ptr to do automatic ref-counting 108// Special functions used by boost::instrusive_ptr to do automatic ref-counting
@@ -135,25 +136,26 @@ public:
135 * Add a thread to wait on this object 136 * Add a thread to wait on this object
136 * @param thread Pointer to thread to add 137 * @param thread Pointer to thread to add
137 */ 138 */
138 void AddWaitingThread(Thread* thread); 139 void AddWaitingThread(SharedPtr<Thread> thread);
139 140
140 /** 141 /**
141 * Removes a thread from waiting on this object (e.g. if it was resumed already) 142 * Removes a thread from waiting on this object (e.g. if it was resumed already)
142 * @param thread Pointer to thread to remove 143 * @param thread Pointer to thread to remove
143 */ 144 */
144 void RemoveWaitingThread(Thread* thead); 145 void RemoveWaitingThread(Thread* thread);
145 146
146 /** 147 /**
147 * Wake up the next thread waiting on this object 148 * Wake up the next thread waiting on this object
148 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting 149 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
149 */ 150 */
150 Thread* WakeupNextThread(); 151 SharedPtr<Thread> WakeupNextThread();
151 152
152 /// Wake up all threads waiting on this object 153 /// Wake up all threads waiting on this object
153 void WakeupAllWaitingThreads(); 154 void WakeupAllWaitingThreads();
154 155
155private: 156private:
156 std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available 157 /// Threads waiting for this object to become available
158 std::vector<SharedPtr<Thread>> waiting_threads;
157}; 159};
158 160
159/** 161/**
@@ -274,7 +276,6 @@ private:
274}; 276};
275 277
276extern HandleTable g_handle_table; 278extern HandleTable g_handle_table;
277extern SharedPtr<Thread> g_main_thread;
278 279
279/// The ID code of the currently running game 280/// The ID code of the currently running game
280/// TODO(Subv): This variable should not be here, 281/// TODO(Subv): This variable should not be here,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index acf484659..9f7166ca4 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -5,6 +5,8 @@
5#include <map> 5#include <map>
6#include <vector> 6#include <vector>
7 7
8#include <boost/range/algorithm_ext/erase.hpp>
9
8#include "common/common.h" 10#include "common/common.h"
9 11
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
@@ -13,9 +15,6 @@
13 15
14namespace Kernel { 16namespace Kernel {
15 17
16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
17static MutexMap g_mutex_held_locks;
18
19/** 18/**
20 * Resumes a thread waiting for the specified mutex 19 * Resumes a thread waiting for the specified mutex
21 * @param mutex The mutex that some thread is waiting on 20 * @param mutex The mutex that some thread is waiting on
@@ -33,21 +32,17 @@ static void ResumeWaitingThread(Mutex* mutex) {
33} 32}
34 33
35void ReleaseThreadMutexes(Thread* thread) { 34void ReleaseThreadMutexes(Thread* thread) {
36 auto locked_range = g_mutex_held_locks.equal_range(thread); 35 for (auto& mtx : thread->held_mutexes) {
37 36 ResumeWaitingThread(mtx.get());
38 // Release every mutex that the thread holds, and resume execution on the waiting threads
39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
40 ResumeWaitingThread(iter->second.get());
41 } 37 }
42 38 thread->held_mutexes.clear();
43 // Erase all the locks that this thread holds
44 g_mutex_held_locks.erase(thread);
45} 39}
46 40
47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { 41Mutex::Mutex() {}
42Mutex::~Mutex() {}
43
44SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
48 SharedPtr<Mutex> mutex(new Mutex); 45 SharedPtr<Mutex> mutex(new Mutex);
49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
51 46
52 mutex->initial_locked = initial_locked; 47 mutex->initial_locked = initial_locked;
53 mutex->locked = false; 48 mutex->locked = false;
@@ -58,7 +53,7 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name)
58 if (initial_locked) 53 if (initial_locked)
59 mutex->Acquire(); 54 mutex->Acquire();
60 55
61 return MakeResult<SharedPtr<Mutex>>(mutex); 56 return mutex;
62} 57}
63 58
64bool Mutex::ShouldWait() { 59bool Mutex::ShouldWait() {
@@ -69,30 +64,22 @@ void Mutex::Acquire() {
69 Acquire(GetCurrentThread()); 64 Acquire(GetCurrentThread());
70} 65}
71 66
72void Mutex::Acquire(Thread* thread) { 67void Mutex::Acquire(SharedPtr<Thread> thread) {
73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 68 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked) 69 if (locked)
75 return; 70 return;
76 71
77 locked = true; 72 locked = true;
78 73
79 g_mutex_held_locks.insert(std::make_pair(thread, this)); 74 thread->held_mutexes.insert(this);
80 holding_thread = thread; 75 holding_thread = std::move(thread);
81} 76}
82 77
83void Mutex::Release() { 78void Mutex::Release() {
84 if (!locked) 79 if (!locked)
85 return; 80 return;
86 81
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread); 82 holding_thread->held_mutexes.erase(this);
88
89 for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
90 if (iter->second == this) {
91 g_mutex_held_locks.erase(iter);
92 break;
93 }
94 }
95
96 ResumeWaitingThread(this); 83 ResumeWaitingThread(this);
97} 84}
98 85
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1e69528f1..548403614 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -22,7 +22,7 @@ public:
22 * @param name Optional name of mutex 22 * @param name Optional name of mutex
23 * @return Pointer to new Mutex object 23 * @return Pointer to new Mutex object
24 */ 24 */
25 static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown"); 25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 26
27 std::string GetTypeName() const override { return "Mutex"; } 27 std::string GetTypeName() const override { return "Mutex"; }
28 std::string GetName() const override { return name; } 28 std::string GetName() const override { return name; }
@@ -43,11 +43,12 @@ public:
43 * @param mutex Mutex that is to be acquired 43 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex 44 * @param thread Thread that will acquire the mutex
45 */ 45 */
46 void Acquire(Thread* thread); 46 void Acquire(SharedPtr<Thread> thread);
47 void Release(); 47 void Release();
48 48
49private: 49private:
50 Mutex() = default; 50 Mutex();
51 ~Mutex() override;
51}; 52};
52 53
53/** 54/**
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index a9e406ef4..c8cf8b9a2 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -10,6 +10,9 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13Semaphore::Semaphore() {}
14Semaphore::~Semaphore() {}
15
13ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
14 std::string name) { 17 std::string name) {
15 18
@@ -18,8 +21,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou
18 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 21 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
19 22
20 SharedPtr<Semaphore> semaphore(new Semaphore); 23 SharedPtr<Semaphore> semaphore(new Semaphore);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
23 24
24 // When the semaphore is created, some slots are reserved for other threads, 25 // When the semaphore is created, some slots are reserved for other threads,
25 // and the rest is reserved for the caller thread 26 // and the rest is reserved for the caller thread
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 9bb404ab6..d8dc1fd78 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -47,7 +47,8 @@ public:
47 ResultVal<s32> Release(s32 release_count); 47 ResultVal<s32> Release(s32 release_count);
48 48
49private: 49private:
50 Semaphore() = default; 50 Semaphore();
51 ~Semaphore() override;
51}; 52};
52 53
53} // namespace 54} // namespace
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
new file mode 100644
index 000000000..0594967f8
--- /dev/null
+++ b/src/core/hle/kernel/session.cpp
@@ -0,0 +1,13 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/session.h"
6#include "core/hle/kernel/thread.h"
7
8namespace Kernel {
9
10Session::Session() {}
11Session::~Session() {}
12
13}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 1788e4375..7cc9332c9 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
8#include "core/mem_map.h"
8 9
9namespace Kernel { 10namespace Kernel {
10 11
@@ -43,6 +44,9 @@ inline static u32* GetCommandBuffer(const int offset=0) {
43 */ 44 */
44class Session : public WaitObject { 45class Session : public WaitObject {
45public: 46public:
47 Session();
48 ~Session() override;
49
46 std::string GetTypeName() const override { return "Session"; } 50 std::string GetTypeName() const override { return "Session"; }
47 51
48 static const HandleType HANDLE_TYPE = HandleType::Session; 52 static const HandleType HANDLE_TYPE = HandleType::Session;
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index eff68d481..4211fcf04 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -9,22 +9,23 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) { 12SharedMemory::SharedMemory() {}
13 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 13SharedMemory::~SharedMemory() {}
14 14
15 // TOOD(yuriks): Don't create Handle (see Thread::Create()) 15SharedPtr<SharedMemory> SharedMemory::Create(std::string name) {
16 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory)); 16 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
17 17
18 shared_memory->name = std::move(name); 18 shared_memory->name = std::move(name);
19 return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory)); 19
20 return shared_memory;
20} 21}
21 22
22ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, 23ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
23 MemoryPermission other_permissions) { 24 MemoryPermission other_permissions) {
24 25
25 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 26 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
26 LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 27 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!",
27 GetHandle(), address); 28 GetObjectId(), address);
28 // TODO: Verify error code with hardware 29 // TODO: Verify error code with hardware
29 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 30 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
30 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 31 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
@@ -41,7 +42,7 @@ ResultVal<u8*> SharedMemory::GetPointer(u32 offset) {
41 if (base_address != 0) 42 if (base_address != 0)
42 return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); 43 return MakeResult<u8*>(Memory::GetPointer(base_address + offset));
43 44
44 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle()); 45 LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId());
45 // TODO(yuriks): Verify error code. 46 // TODO(yuriks): Verify error code.
46 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 47 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
47 ErrorSummary::InvalidState, ErrorLevel::Permanent); 48 ErrorSummary::InvalidState, ErrorLevel::Permanent);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index d393e8175..5833b411c 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -29,7 +29,7 @@ public:
29 * Creates a shared memory object 29 * Creates a shared memory object
30 * @param name Optional object name, used only for debugging purposes. 30 * @param name Optional object name, used only for debugging purposes.
31 */ 31 */
32 static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown"); 32 static SharedPtr<SharedMemory> Create(std::string name = "Unknown");
33 33
34 std::string GetTypeName() const override { return "SharedMemory"; } 34 std::string GetTypeName() const override { return "SharedMemory"; }
35 35
@@ -57,7 +57,8 @@ public:
57 std::string name; ///< Name of shared memory object (optional) 57 std::string name; ///< Name of shared memory object (optional)
58 58
59private: 59private:
60 SharedMemory() = default; 60 SharedMemory();
61 ~SharedMemory() override;
61}; 62};
62 63
63} // namespace 64} // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 56950ebd4..3987f9608 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -4,7 +4,6 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <list> 6#include <list>
7#include <map>
8#include <vector> 7#include <vector>
9 8
10#include "common/common.h" 9#include "common/common.h"
@@ -41,6 +40,9 @@ static Thread* current_thread;
41static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup 40static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
42static u32 next_thread_id; ///< The next available thread id 41static u32 next_thread_id; ///< The next available thread id
43 42
43Thread::Thread() {}
44Thread::~Thread() {}
45
44Thread* GetCurrentThread() { 46Thread* GetCurrentThread() {
45 return current_thread; 47 return current_thread;
46} 48}
@@ -108,6 +110,9 @@ void Thread::Stop(const char* reason) {
108 WakeupAllWaitingThreads(); 110 WakeupAllWaitingThreads();
109 111
110 // Stopped threads are never waiting. 112 // Stopped threads are never waiting.
113 for (auto& wait_object : wait_objects) {
114 wait_object->RemoveWaitingThread(this);
115 }
111 wait_objects.clear(); 116 wait_objects.clear();
112 wait_address = 0; 117 wait_address = 0;
113} 118}
@@ -228,13 +233,15 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
228 233
229/// Event type for the thread wake up event 234/// Event type for the thread wake up event
230static int ThreadWakeupEventType = -1; 235static int ThreadWakeupEventType = -1;
236// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
237// us to simply use a pool index or similar.
238static Kernel::HandleTable wakeup_callback_handle_table;
231 239
232/// Callback that will wake up the thread it was scheduled for 240/// Callback that will wake up the thread it was scheduled for
233static void ThreadWakeupCallback(u64 parameter, int cycles_late) { 241static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
234 Handle handle = static_cast<Handle>(parameter); 242 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
235 SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle);
236 if (thread == nullptr) { 243 if (thread == nullptr) {
237 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); 244 LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", thread_handle);
238 return; 245 return;
239 } 246 }
240 247
@@ -248,14 +255,13 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
248} 255}
249 256
250 257
251void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) { 258void Thread::WakeAfterDelay(s64 nanoseconds) {
252 // Don't schedule a wakeup if the thread wants to wait forever 259 // Don't schedule a wakeup if the thread wants to wait forever
253 if (nanoseconds == -1) 260 if (nanoseconds == -1)
254 return; 261 return;
255 _dbg_assert_(Kernel, thread != nullptr);
256 262
257 u64 microseconds = nanoseconds / 1000; 263 u64 microseconds = nanoseconds / 1000;
258 CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); 264 CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
259} 265}
260 266
261void Thread::ReleaseWaitObject(WaitObject* wait_object) { 267void Thread::ReleaseWaitObject(WaitObject* wait_object) {
@@ -302,7 +308,7 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) {
302 308
303void Thread::ResumeFromWait() { 309void Thread::ResumeFromWait() {
304 // Cancel any outstanding wakeup events 310 // Cancel any outstanding wakeup events
305 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); 311 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
306 312
307 status &= ~THREADSTATUS_WAIT; 313 status &= ~THREADSTATUS_WAIT;
308 314
@@ -326,11 +332,11 @@ static void DebugThreadQueue() {
326 if (!thread) { 332 if (!thread) {
327 return; 333 return;
328 } 334 }
329 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); 335 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId());
330 for (auto& t : thread_list) { 336 for (auto& t : thread_list) {
331 s32 priority = thread_ready_queue.contains(t.get()); 337 s32 priority = thread_ready_queue.contains(t.get());
332 if (priority != -1) { 338 if (priority != -1) {
333 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); 339 LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId());
334 } 340 }
335 } 341 }
336} 342}
@@ -362,14 +368,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
362 368
363 SharedPtr<Thread> thread(new Thread); 369 SharedPtr<Thread> thread(new Thread);
364 370
365 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
366 // the time being. Create a handle here, it will be copied to the handle field in
367 // the object and use by the rest of the code. This should be removed when other
368 // code doesn't rely on the handle anymore.
369 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread);
370 if (handle.Failed())
371 return handle.Code();
372
373 thread_list.push_back(thread); 371 thread_list.push_back(thread);
374 thread_ready_queue.prepare(priority); 372 thread_ready_queue.prepare(priority);
375 373
@@ -385,6 +383,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
385 thread->wait_objects.clear(); 383 thread->wait_objects.clear();
386 thread->wait_address = 0; 384 thread->wait_address = 0;
387 thread->name = std::move(name); 385 thread->name = std::move(name);
386 thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
388 387
389 ResetThread(thread.get(), arg, 0); 388 ResetThread(thread.get(), arg, 0);
390 CallThread(thread.get()); 389 CallThread(thread.get());
@@ -418,16 +417,14 @@ void Thread::SetPriority(s32 priority) {
418 } 417 }
419} 418}
420 419
421Handle SetupIdleThread() { 420SharedPtr<Thread> SetupIdleThread() {
422 // We need to pass a few valid values to get around parameter checking in Thread::Create. 421 // We need to pass a few valid values to get around parameter checking in Thread::Create.
423 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, 422 auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
424 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); 423 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE).MoveFrom();
425 _dbg_assert_(Kernel, thread_res.Succeeded());
426 SharedPtr<Thread> thread = std::move(*thread_res);
427 424
428 thread->idle = true; 425 thread->idle = true;
429 CallThread(thread.get()); 426 CallThread(thread.get());
430 return thread->GetHandle(); 427 return thread;
431} 428}
432 429
433SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { 430SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) {
@@ -460,13 +457,13 @@ void Reschedule() {
460 HLE::g_reschedule = false; 457 HLE::g_reschedule = false;
461 458
462 if (next != nullptr) { 459 if (next != nullptr) {
463 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); 460 LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId());
464 SwitchContext(next); 461 SwitchContext(next);
465 } else { 462 } else {
466 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 463 LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId());
467 464
468 for (auto& thread : thread_list) { 465 for (auto& thread : thread_list) {
469 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), 466 LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(),
470 thread->current_priority, thread->status); 467 thread->current_priority, thread->status);
471 } 468 }
472 } 469 }
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index d6299364a..633bb7c98 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -7,6 +7,8 @@
7#include <string> 7#include <string>
8#include <vector> 8#include <vector>
9 9
10#include <boost/container/flat_set.hpp>
11
10#include "common/common_types.h" 12#include "common/common_types.h"
11 13
12#include "core/core.h" 14#include "core/core.h"
@@ -40,6 +42,8 @@ enum ThreadStatus {
40 42
41namespace Kernel { 43namespace Kernel {
42 44
45class Mutex;
46
43class Thread final : public WaitObject { 47class Thread final : public WaitObject {
44public: 48public:
45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 49 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
@@ -78,6 +82,12 @@ public:
78 void ResumeFromWait(); 82 void ResumeFromWait();
79 83
80 /** 84 /**
85 * Schedules an event to wake up the specified thread after the specified delay.
86 * @param nanoseconds The time this thread will be allowed to sleep for.
87 */
88 void WakeAfterDelay(s64 nanoseconds);
89
90 /**
81 * Sets the result after the thread awakens (from either WaitSynchronization SVC) 91 * Sets the result after the thread awakens (from either WaitSynchronization SVC)
82 * @param result Value to set to the returned result 92 * @param result Value to set to the returned result
83 */ 93 */
@@ -103,8 +113,10 @@ public:
103 113
104 s32 processor_id; 114 s32 processor_id;
105 115
106 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 116 /// Mutexes currently held by this thread, which will be released when it exits.
117 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
107 118
119 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
108 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 120 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
109 bool wait_all; ///< True if the thread is waiting on all objects before resuming 121 bool wait_all; ///< True if the thread is waiting on all objects before resuming
110 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup 122 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
@@ -115,9 +127,15 @@ public:
115 bool idle = false; 127 bool idle = false;
116 128
117private: 129private:
118 Thread() = default; 130 Thread();
131 ~Thread() override;
132
133 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
134 Handle callback_handle;
119}; 135};
120 136
137extern SharedPtr<Thread> g_main_thread;
138
121/// Sets up the primary application thread 139/// Sets up the primary application thread
122SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); 140SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size);
123 141
@@ -151,19 +169,12 @@ void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bo
151void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); 169void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
152 170
153/** 171/**
154 * Schedules an event to wake up the specified thread after the specified delay.
155 * @param handle The thread handle.
156 * @param nanoseconds The time this thread will be allowed to sleep for.
157 */
158void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds);
159
160/**
161 * Sets up the idle thread, this is a thread that is intended to never execute instructions, 172 * Sets up the idle thread, this is a thread that is intended to never execute instructions,
162 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue 173 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
163 * and will try to yield on every call. 174 * and will try to yield on every call.
164 * @returns The handle of the idle thread 175 * @returns The handle of the idle thread
165 */ 176 */
166Handle SetupIdleThread(); 177SharedPtr<Thread> SetupIdleThread();
167 178
168/// Initialize threading 179/// Initialize threading
169void ThreadingInit(); 180void ThreadingInit();
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 503a5d2ce..4352fc99c 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <set>
6
7#include "common/common.h" 5#include "common/common.h"
8 6
9#include "core/core_timing.h" 7#include "core/core_timing.h"
@@ -15,18 +13,24 @@ namespace Kernel {
15 13
16/// The event type of the generic timer callback event 14/// The event type of the generic timer callback event
17static int timer_callback_event_type = -1; 15static int timer_callback_event_type = -1;
16// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
17// us to simply use a pool index or similar.
18static Kernel::HandleTable timer_callback_handle_table;
19
20Timer::Timer() {}
21Timer::~Timer() {}
18 22
19ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) { 23SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
20 SharedPtr<Timer> timer(new Timer); 24 SharedPtr<Timer> timer(new Timer);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer));
23 25
24 timer->reset_type = reset_type; 26 timer->reset_type = reset_type;
25 timer->signaled = false; 27 timer->signaled = false;
26 timer->name = std::move(name); 28 timer->name = std::move(name);
27 timer->initial_delay = 0; 29 timer->initial_delay = 0;
28 timer->interval_delay = 0; 30 timer->interval_delay = 0;
29 return MakeResult<SharedPtr<Timer>>(timer); 31 timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
32
33 return timer;
30} 34}
31 35
32bool Timer::ShouldWait() { 36bool Timer::ShouldWait() {
@@ -38,17 +42,19 @@ void Timer::Acquire() {
38} 42}
39 43
40void Timer::Set(s64 initial, s64 interval) { 44void Timer::Set(s64 initial, s64 interval) {
45 // Ensure we get rid of any previous scheduled event
46 Cancel();
47
41 initial_delay = initial; 48 initial_delay = initial;
42 interval_delay = interval; 49 interval_delay = interval;
43 50
44 u64 initial_microseconds = initial / 1000; 51 u64 initial_microseconds = initial / 1000;
45 // TODO(yuriks): Figure out a replacement for GetHandle here 52 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds),
46 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, 53 timer_callback_event_type, callback_handle);
47 GetHandle());
48} 54}
49 55
50void Timer::Cancel() { 56void Timer::Cancel() {
51 CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle()); 57 CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
52} 58}
53 59
54void Timer::Clear() { 60void Timer::Clear() {
@@ -57,7 +63,7 @@ void Timer::Clear() {
57 63
58/// The timer callback event, called when a timer is fired 64/// The timer callback event, called when a timer is fired
59static void TimerCallback(u64 timer_handle, int cycles_late) { 65static void TimerCallback(u64 timer_handle, int cycles_late) {
60 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); 66 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle);
61 67
62 if (timer == nullptr) { 68 if (timer == nullptr) {
63 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); 69 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index c45e79954..540e4e187 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -19,7 +19,7 @@ public:
19 * @param name Optional name of timer 19 * @param name Optional name of timer
20 * @return The created Timer 20 * @return The created Timer
21 */ 21 */
22 static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown"); 22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 23
24 std::string GetTypeName() const override { return "Timer"; } 24 std::string GetTypeName() const override { return "Timer"; }
25 std::string GetName() const override { return name; } 25 std::string GetName() const override { return name; }
@@ -49,7 +49,11 @@ public:
49 void Clear(); 49 void Clear();
50 50
51private: 51private:
52 Timer() = default; 52 Timer();
53 ~Timer() override;
54
55 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
56 Handle callback_handle;
53}; 57};
54 58
55/// Initializes the required variables for timers 59/// Initializes the required variables for timers
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 20a3fa2e5..53d920de1 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -53,7 +53,7 @@ const Interface::FunctionInfo FunctionTable[] = {
53// Interface class 53// Interface class
54 54
55Interface::Interface() { 55Interface::Interface() {
56 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 56 Register(FunctionTable);
57} 57}
58 58
59} // namespace 59} // namespace
diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp
index 10870f14b..4ea7a9fb2 100644
--- a/src/core/hle/service/act_u.cpp
+++ b/src/core/hle/service/act_u.cpp
@@ -18,7 +18,7 @@ namespace ACT_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp
index 0b396b6d3..df10db87f 100644
--- a/src/core/hle/service/am_app.cpp
+++ b/src/core/hle/service/am_app.cpp
@@ -18,7 +18,7 @@ namespace AM_APP {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
index 112844e5b..c74012d9d 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am_net.cpp
@@ -38,7 +38,7 @@ const Interface::FunctionInfo FunctionTable[] = {
38// Interface class 38// Interface class
39 39
40Interface::Interface() { 40Interface::Interface() {
41 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 41 Register(FunctionTable);
42} 42}
43 43
44} // namespace 44} // namespace
diff --git a/src/core/hle/service/am_sys.cpp b/src/core/hle/service/am_sys.cpp
index b63c8c087..c5df8abda 100644
--- a/src/core/hle/service/am_sys.cpp
+++ b/src/core/hle/service/am_sys.cpp
@@ -18,7 +18,7 @@ namespace AM_SYS {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp
index 42f2879c1..e1dd2a5fb 100644
--- a/src/core/hle/service/apt_a.cpp
+++ b/src/core/hle/service/apt_a.cpp
@@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = {
39// Interface class 39// Interface class
40 40
41Interface::Interface() { 41Interface::Interface() {
42 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 42 Register(FunctionTable);
43} 43}
44 44
45} // namespace 45} // namespace
diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp
index 7ad428ee7..686335428 100644
--- a/src/core/hle/service/apt_s.cpp
+++ b/src/core/hle/service/apt_s.cpp
@@ -117,7 +117,7 @@ const Interface::FunctionInfo FunctionTable[] = {
117// Interface class 117// Interface class
118 118
119Interface::Interface() { 119Interface::Interface() {
120 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 120 Register(FunctionTable);
121} 121}
122 122
123} // namespace 123} // namespace
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 4c3f621d0..ccfd04591 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -69,8 +69,8 @@ void Initialize(Service::Interface* self) {
69 u32* cmd_buff = Kernel::GetCommandBuffer(); 69 u32* cmd_buff = Kernel::GetCommandBuffer();
70 70
71 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 71 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
72 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom(); 72 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
73 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom(); 73 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause");
74 74
75 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 75 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
76 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); 76 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom();
@@ -512,15 +512,15 @@ Interface::Interface() {
512 file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); 512 file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
513 513
514 // Create shared font memory object 514 // Create shared font memory object
515 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom(); 515 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem");
516 } else { 516 } else {
517 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); 517 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
518 shared_font_mem = nullptr; 518 shared_font_mem = nullptr;
519 } 519 }
520 520
521 lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); 521 lock = Kernel::Mutex::Create(false, "APT_U:Lock");
522 522
523 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 523 Register(FunctionTable);
524} 524}
525 525
526} // namespace 526} // namespace
diff --git a/src/core/hle/service/boss_p.cpp b/src/core/hle/service/boss_p.cpp
index f245a38e9..b3aa6acee 100644
--- a/src/core/hle/service/boss_p.cpp
+++ b/src/core/hle/service/boss_p.cpp
@@ -18,7 +18,7 @@ namespace BOSS_P {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp
index 1820ea7ad..50bb5d426 100644
--- a/src/core/hle/service/boss_u.cpp
+++ b/src/core/hle/service/boss_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp
index 549095339..cf3b27664 100644
--- a/src/core/hle/service/cam_u.cpp
+++ b/src/core/hle/service/cam_u.cpp
@@ -18,7 +18,7 @@ namespace CAM_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cecd_s.cpp b/src/core/hle/service/cecd_s.cpp
index 9c4992f13..2c707baff 100644
--- a/src/core/hle/service/cecd_s.cpp
+++ b/src/core/hle/service/cecd_s.cpp
@@ -18,7 +18,7 @@ namespace CECD_S {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp
index b7655ef0b..b7ea3a186 100644
--- a/src/core/hle/service/cecd_u.cpp
+++ b/src/core/hle/service/cecd_u.cpp
@@ -18,7 +18,7 @@ namespace CECD_U {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 7c1ee8ac3..555b7884a 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -104,7 +104,7 @@ const Interface::FunctionInfo FunctionTable[] = {
104// Interface class 104// Interface class
105 105
106Interface::Interface() { 106Interface::Interface() {
107 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 107 Register(FunctionTable);
108} 108}
109 109
110} // namespace 110} // namespace
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index cf4e82152..2170894d6 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -92,7 +92,7 @@ const Interface::FunctionInfo FunctionTable[] = {
92// Interface class 92// Interface class
93 93
94Interface::Interface() { 94Interface::Interface() {
95 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 95 Register(FunctionTable);
96} 96}
97 97
98} // namespace 98} // namespace
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 835620909..1da9f59f6 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -186,7 +186,7 @@ const Interface::FunctionInfo FunctionTable[] = {
186// Interface class 186// Interface class
187 187
188Interface::Interface() { 188Interface::Interface() {
189 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 189 Register(FunctionTable);
190} 190}
191 191
192} // namespace 192} // namespace
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 3a557efe1..39b00982c 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
29// Interface class 29// Interface class
30 30
31Interface::Interface() { 31Interface::Interface() {
32 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 32 Register(FunctionTable);
33} 33}
34 34
35} // namespace 35} // namespace
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 9a38be393..0f86894a6 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -201,12 +201,11 @@ const Interface::FunctionInfo FunctionTable[] = {
201// Interface class 201// Interface class
202 202
203Interface::Interface() { 203Interface::Interface() {
204 semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, 204 semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
205 "DSP_DSP::semaphore_event").MoveFrom();
206 interrupt_event = nullptr; 205 interrupt_event = nullptr;
207 read_pipe_count = 0; 206 read_pipe_count = 0;
208 207
209 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 208 Register(FunctionTable);
210} 209}
211 210
212} // namespace 211} // namespace
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 8c900eabc..962de2170 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/frd_a.cpp b/src/core/hle/service/frd_a.cpp
index 53edc2cd8..79140a756 100644
--- a/src/core/hle/service/frd_a.cpp
+++ b/src/core/hle/service/frd_a.cpp
@@ -18,7 +18,7 @@ namespace FRD_A {
18// Interface class 18// Interface class
19 19
20Interface::Interface() { 20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 21 //Register(FunctionTable);
22} 22}
23 23
24} // namespace 24} // namespace
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp
index 021186e57..59faca77a 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd_u.cpp
@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
27// Interface class 27// Interface class
28 28
29Interface::Interface() { 29Interface::Interface() {
30 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 30 Register(FunctionTable);
31} 31}
32 32
33} // namespace 33} // namespace
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 43eef034e..ccf132f31 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -163,7 +163,7 @@ public:
163 case FileCommand::OpenLinkFile: 163 case FileCommand::OpenLinkFile:
164 { 164 {
165 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); 165 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
166 cmd_buff[3] = GetHandle(); 166 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
167 break; 167 break;
168 } 168 }
169 169
@@ -303,7 +303,8 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
303 return RESULT_SUCCESS; 303 return RESULT_SUCCESS;
304} 304}
305 305
306ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { 306ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
307 const FileSys::Path& path, const FileSys::Mode mode) {
307 Archive* archive = GetArchive(archive_handle); 308 Archive* archive = GetArchive(archive_handle);
308 if (archive == nullptr) 309 if (archive == nullptr)
309 return ERR_INVALID_HANDLE; 310 return ERR_INVALID_HANDLE;
@@ -314,10 +315,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
314 ErrorSummary::NotFound, ErrorLevel::Status); 315 ErrorSummary::NotFound, ErrorLevel::Status);
315 } 316 }
316 317
317 auto file = Common::make_unique<File>(std::move(backend), path); 318 auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path));
318 // TOOD(yuriks): Fix error reporting 319 return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file));
319 Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
320 return MakeResult<Handle>(handle);
321} 320}
322 321
323ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 322ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
@@ -403,13 +402,8 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
403 ErrorSummary::NothingHappened, ErrorLevel::Status); 402 ErrorSummary::NothingHappened, ErrorLevel::Status);
404} 403}
405 404
406/** 405ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
407 * Open a Directory from an Archive 406 const FileSys::Path& path) {
408 * @param archive_handle Handle to an open Archive object
409 * @param path Path to the Directory inside of the Archive
410 * @return Opened Directory object
411 */
412ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
413 Archive* archive = GetArchive(archive_handle); 407 Archive* archive = GetArchive(archive_handle);
414 if (archive == nullptr) 408 if (archive == nullptr)
415 return ERR_INVALID_HANDLE; 409 return ERR_INVALID_HANDLE;
@@ -420,10 +414,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
420 ErrorSummary::NotFound, ErrorLevel::Permanent); 414 ErrorSummary::NotFound, ErrorLevel::Permanent);
421 } 415 }
422 416
423 auto directory = Common::make_unique<Directory>(std::move(backend), path); 417 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
424 // TOOD(yuriks): Fix error reporting 418 return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory));
425 Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
426 return MakeResult<Handle>(handle);
427} 419}
428 420
429ResultCode FormatSaveData() { 421ResultCode FormatSaveData() {
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index ba674d7f6..ab5ea4da8 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -15,6 +15,10 @@ extern const std::string SYSTEM_ID;
15/// The scrambled SD card CID, also known as ID1 15/// The scrambled SD card CID, also known as ID1
16extern const std::string SDCARD_ID; 16extern const std::string SDCARD_ID;
17 17
18namespace Kernel {
19 class Session;
20}
21
18namespace Service { 22namespace Service {
19namespace FS { 23namespace FS {
20 24
@@ -58,9 +62,10 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
58 * @param archive_handle Handle to an open Archive object 62 * @param archive_handle Handle to an open Archive object
59 * @param path Path to the File inside of the Archive 63 * @param path Path to the File inside of the Archive
60 * @param mode Mode under which to open the File 64 * @param mode Mode under which to open the File
61 * @return Handle to the opened File object 65 * @return The opened File object as a Session
62 */ 66 */
63ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); 67ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
68 const FileSys::Path& path, const FileSys::Mode mode);
64 69
65/** 70/**
66 * Delete a File from an Archive 71 * Delete a File from an Archive
@@ -121,9 +126,10 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
121 * Open a Directory from an Archive 126 * Open a Directory from an Archive
122 * @param archive_handle Handle to an open Archive object 127 * @param archive_handle Handle to an open Archive object
123 * @param path Path to the Directory inside of the Archive 128 * @param path Path to the Directory inside of the Archive
124 * @return Handle to the opened File object 129 * @return The opened Directory object as a Session
125 */ 130 */
126ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); 131ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
132 const FileSys::Path& path);
127 133
128/** 134/**
129 * Creates a blank SaveData archive. 135 * Creates a blank SaveData archive.
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index c495b6f3c..94a3a31c8 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -14,6 +14,9 @@
14//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
15// Namespace FS_User 15// Namespace FS_User
16 16
17using Kernel::SharedPtr;
18using Kernel::Session;
19
17namespace Service { 20namespace Service {
18namespace FS { 21namespace FS {
19 22
@@ -58,10 +61,10 @@ static void OpenFile(Service::Interface* self) {
58 61
59 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 62 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
60 63
61 ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode); 64 ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
62 cmd_buff[1] = handle.Code().raw; 65 cmd_buff[1] = file_res.Code().raw;
63 if (handle.Succeeded()) { 66 if (file_res.Succeeded()) {
64 cmd_buff[3] = *handle; 67 cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
65 } else { 68 } else {
66 cmd_buff[3] = 0; 69 cmd_buff[3] = 0;
67 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 70 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) {
114 } 117 }
115 SCOPE_EXIT({ CloseArchive(*archive_handle); }); 118 SCOPE_EXIT({ CloseArchive(*archive_handle); });
116 119
117 ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode); 120 ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode);
118 cmd_buff[1] = handle.Code().raw; 121 cmd_buff[1] = file_res.Code().raw;
119 if (handle.Succeeded()) { 122 if (file_res.Succeeded()) {
120 cmd_buff[3] = *handle; 123 cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
121 } else { 124 } else {
122 cmd_buff[3] = 0; 125 cmd_buff[3] = 0;
123 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 126 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) {
334 337
335 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 338 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
336 339
337 ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path); 340 ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
338 cmd_buff[1] = handle.Code().raw; 341 cmd_buff[1] = dir_res.Code().raw;
339 if (handle.Succeeded()) { 342 if (dir_res.Succeeded()) {
340 cmd_buff[3] = *handle; 343 cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom();
341 } else { 344 } else {
342 LOG_ERROR(Service_FS, "failed to get a handle for directory"); 345 LOG_ERROR(Service_FS, "failed to get a handle for directory");
343 } 346 }
@@ -588,7 +591,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
588// Interface class 591// Interface class
589 592
590FSUserInterface::FSUserInterface() { 593FSUserInterface::FSUserInterface() {
591 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 594 Register(FunctionTable);
592} 595}
593 596
594} // namespace FS 597} // namespace FS
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 5b91f17d2..495c117ee 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -187,7 +187,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
187 187
188 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]); 188 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
189 _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!"); 189 _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!");
190 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); 190 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem");
191 191
192 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); 192 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
193 193
@@ -389,7 +389,7 @@ const Interface::FunctionInfo FunctionTable[] = {
389// Interface class 389// Interface class
390 390
391Interface::Interface() { 391Interface::Interface() {
392 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 392 Register(FunctionTable);
393 393
394 g_interrupt_event = 0; 394 g_interrupt_event = 0;
395 g_shared_memory = 0; 395 g_shared_memory = 0;
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index 6213472ff..d63fa1ee2 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -20,7 +20,7 @@ namespace GSP_LCD {
20// Interface class 20// Interface class
21 21
22Interface::Interface() { 22Interface::Interface() {
23 //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 23 //Register(FunctionTable);
24} 24}
25 25
26} // namespace 26} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 835055af4..7cb01729e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -30,6 +30,8 @@ static s16 next_circle_y = 0;
30 * Gets a pointer to the PadData structure inside HID shared memory 30 * Gets a pointer to the PadData structure inside HID shared memory
31 */ 31 */
32static inline PadData* GetPadData() { 32static inline PadData* GetPadData() {
33 if (g_shared_mem == nullptr)
34 return nullptr;
33 return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr)); 35 return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr));
34} 36}
35 37
@@ -122,14 +124,14 @@ void PadUpdateComplete() {
122void HIDInit() { 124void HIDInit() {
123 using namespace Kernel; 125 using namespace Kernel;
124 126
125 g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom(); 127 g_shared_mem = SharedMemory::Create("HID:SharedMem");
126 128
127 // Create event handles 129 // Create event handles
128 g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom(); 130 g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1");
129 g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom(); 131 g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2");
130 g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom(); 132 g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer");
131 g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom(); 133 g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope");
132 g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom(); 134 g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad");
133} 135}
134 136
135void HIDShutdown() { 137void HIDShutdown() {
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 76c40b659..054aa8b59 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -32,7 +32,7 @@ const Interface::FunctionInfo FunctionTable[] = {
32// Interface class 32// Interface class
33 33
34Interface::Interface() { 34Interface::Interface() {
35 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 35 Register(FunctionTable);
36} 36}
37 37
38} // namespace 38} // namespace
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index 5444aa5ee..68edafebb 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -72,7 +72,7 @@ const Interface::FunctionInfo FunctionTable[] = {
72// Interface class 72// Interface class
73 73
74Interface::Interface() { 74Interface::Interface() {
75 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 75 Register(FunctionTable);
76} 76}
77 77
78} // namespace 78} // namespace
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index d0bff552f..6595ca572 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = {
58// Interface class 58// Interface class
59 59
60Interface::Interface() { 60Interface::Interface() {
61 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 61 Register(FunctionTable);
62} 62}
63 63
64} // namespace 64} // namespace
diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp
index d49bd5335..31da8e160 100644
--- a/src/core/hle/service/ir_rst.cpp
+++ b/src/core/hle/service/ir_rst.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp
index da6f38e41..7fa233048 100644
--- a/src/core/hle/service/ir_u.cpp
+++ b/src/core/hle/service/ir_u.cpp
@@ -36,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
36// Interface class 36// Interface class
37 37
38Interface::Interface() { 38Interface::Interface() {
39 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 39 Register(FunctionTable);
40} 40}
41 41
42} // namespace 42} // namespace
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index 7d6e2e8e8..459717fff 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
27// Interface class 27// Interface class
28 28
29Interface::Interface() { 29Interface::Interface() {
30 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 30 Register(FunctionTable);
31} 31}
32 32
33} // namespace 33} // namespace
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 82bce9180..af967b5b6 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = {
34// Interface class 34// Interface class
35 35
36Interface::Interface() { 36Interface::Interface() {
37 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 37 Register(FunctionTable);
38} 38}
39 39
40} // namespace 40} // namespace
diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp
index 0f03de6ae..df3c97193 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -24,7 +24,7 @@ const Interface::FunctionInfo FunctionTable[] = {
24// Interface class 24// Interface class
25 25
26Interface::Interface() { 26Interface::Interface() {
27 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 27 Register(FunctionTable);
28} 28}
29 29
30} // namespace 30} // namespace
diff --git a/src/core/hle/service/news_s.cpp b/src/core/hle/service/news_s.cpp
index 1850f59bd..d7537875b 100644
--- a/src/core/hle/service/news_s.cpp
+++ b/src/core/hle/service/news_s.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp
index b5adad4c6..a9e161c23 100644
--- a/src/core/hle/service/news_u.cpp
+++ b/src/core/hle/service/news_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
19// Interface class 19// Interface class
20 20
21Interface::Interface() { 21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 22 Register(FunctionTable);
23} 23}
24 24
25} // namespace 25} // namespace
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp
index 17d1c4ff5..ab2ef4429 100644
--- a/src/core/hle/service/nim_aoc.cpp
+++ b/src/core/hle/service/nim_aoc.cpp
@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
25// Interface class 25// Interface class
26 26
27Interface::Interface() { 27Interface::Interface() {
28 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 28 Register(FunctionTable);
29} 29}
30 30
31} // namespace 31} // namespace
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
index b9aca4257..5cf3e2039 100644
--- a/src/core/hle/service/ns_s.cpp
+++ b/src/core/hle/service/ns_s.cpp
@@ -21,7 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = {
21// Interface class 21// Interface class
22 22
23Interface::Interface() { 23Interface::Interface() {
24 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 24 Register(FunctionTable);
25} 25}
26 26
27} // namespace 27} // namespace
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index ce456a966..61fcb54ce 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
26// Interface class 26// Interface class
27 27
28Interface::Interface() { 28Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable);
30} 30}
31 31
32} // namespace 32} // namespace
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 529dccafb..d61eaf80f 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
26// Interface class 26// Interface class
27 27
28Interface::Interface() { 28Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable);
30} 30}
31 31
32} // namespace 32} // namespace
diff --git a/src/core/hle/service/ptm_play.cpp b/src/core/hle/service/ptm_play.cpp
index ae9e2925c..b357057fd 100644
--- a/src/core/hle/service/ptm_play.cpp
+++ b/src/core/hle/service/ptm_play.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/ptm_sysm.cpp b/src/core/hle/service/ptm_sysm.cpp
index 4b5f86a47..b6f688de3 100644
--- a/src/core/hle/service/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm_sysm.cpp
@@ -50,7 +50,7 @@ const Interface::FunctionInfo FunctionTable[] = {
50// Interface class 50// Interface class
51 51
52Interface::Interface() { 52Interface::Interface() {
53 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 53 Register(FunctionTable);
54} 54}
55 55
56} // namespace 56} // namespace
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index 753180add..7b465a348 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -137,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = {
137// Interface class 137// Interface class
138 138
139Interface::Interface() { 139Interface::Interface() {
140 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 140 Register(FunctionTable);
141 // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file 141 // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file
142 // TODO(Subv): In the future we should use the FS service to query this archive 142 // TODO(Subv): In the future we should use the FS service to query this archive
143 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); 143 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 355196fd3..e0979ea5d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -54,96 +54,76 @@
54 54
55namespace Service { 55namespace Service {
56 56
57Manager* g_manager = nullptr; ///< Service manager 57std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
58std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
58 59
59//////////////////////////////////////////////////////////////////////////////////////////////////// 60////////////////////////////////////////////////////////////////////////////////////////////////////
60// Service Manager class 61// Module interface
61
62void Manager::AddService(Interface* service) {
63 // TOOD(yuriks): Fix error reporting
64 m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
65 m_services.push_back(service);
66}
67
68void Manager::DeleteService(const std::string& port_name) {
69 Interface* service = FetchFromPortName(port_name);
70 m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end());
71 m_port_map.erase(port_name);
72}
73 62
74Interface* Manager::FetchFromHandle(Handle handle) { 63static void AddNamedPort(Interface* interface) {
75 // TODO(yuriks): This function is very suspicious and should probably be exterminated. 64 g_kernel_named_ports.emplace(interface->GetPortName(), interface);
76 return Kernel::g_handle_table.Get<Interface>(handle).get();
77} 65}
78 66
79Interface* Manager::FetchFromPortName(const std::string& port_name) { 67static void AddService(Interface* interface) {
80 auto itr = m_port_map.find(port_name); 68 g_srv_services.emplace(interface->GetPortName(), interface);
81 if (itr == m_port_map.end()) {
82 return nullptr;
83 }
84 return FetchFromHandle(itr->second);
85} 69}
86 70
87
88////////////////////////////////////////////////////////////////////////////////////////////////////
89// Module interface
90
91/// Initialize ServiceManager 71/// Initialize ServiceManager
92void Init() { 72void Init() {
93 g_manager = new Manager; 73 AddNamedPort(new SRV::Interface);
94 74
95 g_manager->AddService(new SRV::Interface); 75 AddService(new AC_U::Interface);
96 g_manager->AddService(new AC_U::Interface); 76 AddService(new ACT_U::Interface);
97 g_manager->AddService(new ACT_U::Interface); 77 AddService(new AM_APP::Interface);
98 g_manager->AddService(new AM_APP::Interface); 78 AddService(new AM_NET::Interface);
99 g_manager->AddService(new AM_NET::Interface); 79 AddService(new AM_SYS::Interface);
100 g_manager->AddService(new AM_SYS::Interface); 80 AddService(new APT_A::Interface);
101 g_manager->AddService(new APT_A::Interface); 81 AddService(new APT_S::Interface);
102 g_manager->AddService(new APT_S::Interface); 82 AddService(new APT_U::Interface);
103 g_manager->AddService(new APT_U::Interface); 83 AddService(new BOSS_P::Interface);
104 g_manager->AddService(new BOSS_P::Interface); 84 AddService(new BOSS_U::Interface);
105 g_manager->AddService(new BOSS_U::Interface); 85 AddService(new CAM_U::Interface);
106 g_manager->AddService(new CAM_U::Interface); 86 AddService(new CECD_S::Interface);
107 g_manager->AddService(new CECD_S::Interface); 87 AddService(new CECD_U::Interface);
108 g_manager->AddService(new CECD_U::Interface); 88 AddService(new CFG_I::Interface);
109 g_manager->AddService(new CFG_I::Interface); 89 AddService(new CFG_S::Interface);
110 g_manager->AddService(new CFG_S::Interface); 90 AddService(new CFG_U::Interface);
111 g_manager->AddService(new CFG_U::Interface); 91 AddService(new CSND_SND::Interface);
112 g_manager->AddService(new CSND_SND::Interface); 92 AddService(new DSP_DSP::Interface);
113 g_manager->AddService(new DSP_DSP::Interface); 93 AddService(new ERR_F::Interface);
114 g_manager->AddService(new ERR_F::Interface); 94 AddService(new FRD_A::Interface);
115 g_manager->AddService(new FRD_A::Interface); 95 AddService(new FRD_U::Interface);
116 g_manager->AddService(new FRD_U::Interface); 96 AddService(new FS::FSUserInterface);
117 g_manager->AddService(new FS::FSUserInterface); 97 AddService(new GSP_GPU::Interface);
118 g_manager->AddService(new GSP_GPU::Interface); 98 AddService(new GSP_LCD::Interface);
119 g_manager->AddService(new GSP_LCD::Interface); 99 AddService(new HID_User::Interface);
120 g_manager->AddService(new HID_User::Interface); 100 AddService(new HID_SPVR::Interface);
121 g_manager->AddService(new HID_SPVR::Interface); 101 AddService(new HTTP_C::Interface);
122 g_manager->AddService(new HTTP_C::Interface); 102 AddService(new IR_RST::Interface);
123 g_manager->AddService(new IR_RST::Interface); 103 AddService(new IR_U::Interface);
124 g_manager->AddService(new IR_U::Interface); 104 AddService(new LDR_RO::Interface);
125 g_manager->AddService(new LDR_RO::Interface); 105 AddService(new MIC_U::Interface);
126 g_manager->AddService(new MIC_U::Interface); 106 AddService(new NDM_U::Interface);
127 g_manager->AddService(new NDM_U::Interface); 107 AddService(new NEWS_S::Interface);
128 g_manager->AddService(new NEWS_S::Interface); 108 AddService(new NEWS_U::Interface);
129 g_manager->AddService(new NEWS_U::Interface); 109 AddService(new NIM_AOC::Interface);
130 g_manager->AddService(new NIM_AOC::Interface); 110 AddService(new NS_S::Interface);
131 g_manager->AddService(new NS_S::Interface); 111 AddService(new NWM_UDS::Interface);
132 g_manager->AddService(new NWM_UDS::Interface); 112 AddService(new PM_APP::Interface);
133 g_manager->AddService(new PM_APP::Interface); 113 AddService(new PTM_PLAY::Interface);
134 g_manager->AddService(new PTM_PLAY::Interface); 114 AddService(new PTM_U::Interface);
135 g_manager->AddService(new PTM_U::Interface); 115 AddService(new PTM_SYSM::Interface);
136 g_manager->AddService(new PTM_SYSM::Interface); 116 AddService(new SOC_U::Interface);
137 g_manager->AddService(new SOC_U::Interface); 117 AddService(new SSL_C::Interface);
138 g_manager->AddService(new SSL_C::Interface); 118 AddService(new Y2R_U::Interface);
139 g_manager->AddService(new Y2R_U::Interface);
140 119
141 LOG_DEBUG(Service, "initialized OK"); 120 LOG_DEBUG(Service, "initialized OK");
142} 121}
143 122
144/// Shutdown ServiceManager 123/// Shutdown ServiceManager
145void Shutdown() { 124void Shutdown() {
146 delete g_manager; 125 g_srv_services.clear();
126 g_kernel_named_ports.clear();
147 LOG_DEBUG(Service, "shutdown OK"); 127 LOG_DEBUG(Service, "shutdown OK");
148} 128}
149 129
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e75d5008b..3370f9f9b 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -5,9 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <vector>
9#include <map>
10#include <string> 8#include <string>
9#include <unordered_map>
10#include <vector>
11
12#include <boost/container/flat_map.hpp>
11 13
12#include "common/common.h" 14#include "common/common.h"
13#include "common/string_util.h" 15#include "common/string_util.h"
@@ -27,7 +29,7 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character
27class Manager; 29class Manager;
28 30
29/// Interface to a CTROS service 31/// Interface to a CTROS service
30class Interface : public Kernel::Session { 32class Interface : public Kernel::Session {
31 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be 33 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
32 // just something that encapsulates a session and acts as a helper to implement service 34 // just something that encapsulates a session and acts as a helper to implement service
33 // processes. 35 // processes.
@@ -38,11 +40,11 @@ class Interface : public Kernel::Session {
38 * Creates a function string for logging, complete with the name (or header code, depending 40 * Creates a function string for logging, complete with the name (or header code, depending
39 * on what's passed in) the port name, and all the cmd_buff arguments. 41 * on what's passed in) the port name, and all the cmd_buff arguments.
40 */ 42 */
41 std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) { 43 std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
42 // Number of params == bits 0-5 + bits 6-11 44 // Number of params == bits 0-5 + bits 6-11
43 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 45 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
44 46
45 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str()); 47 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
46 for (int i = 1; i <= num_params; ++i) { 48 for (int i = 1; i <= num_params; ++i) {
47 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); 49 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
48 } 50 }
@@ -57,7 +59,7 @@ public:
57 struct FunctionInfo { 59 struct FunctionInfo {
58 u32 id; 60 u32 id;
59 Function func; 61 Function func;
60 std::string name; 62 const char* name;
61 }; 63 };
62 64
63 /** 65 /**
@@ -68,34 +70,19 @@ public:
68 return "[UNKNOWN SERVICE PORT]"; 70 return "[UNKNOWN SERVICE PORT]";
69 } 71 }
70 72
71 /// Allocates a new handle for the service
72 Handle CreateHandle(Kernel::Object *obj) {
73 // TODO(yuriks): Fix error reporting
74 Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
75 m_handles.push_back(handle);
76 return handle;
77 }
78
79 /// Frees a handle from the service
80 template <class T>
81 void DeleteHandle(const Handle handle) {
82 Kernel::g_handle_table.Close(handle);
83 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
84 }
85
86 ResultVal<bool> SyncRequest() override { 73 ResultVal<bool> SyncRequest() override {
87 u32* cmd_buff = Kernel::GetCommandBuffer(); 74 u32* cmd_buff = Kernel::GetCommandBuffer();
88 auto itr = m_functions.find(cmd_buff[0]); 75 auto itr = m_functions.find(cmd_buff[0]);
89 76
90 if (itr == m_functions.end() || itr->second.func == nullptr) { 77 if (itr == m_functions.end() || itr->second.func == nullptr) {
91 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; 78 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
92 LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str()); 79 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
93 80
94 // TODO(bunnei): Hack - ignore error 81 // TODO(bunnei): Hack - ignore error
95 cmd_buff[1] = 0; 82 cmd_buff[1] = 0;
96 return MakeResult<bool>(false); 83 return MakeResult<bool>(false);
97 } else { 84 } else {
98 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str()); 85 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
99 } 86 }
100 87
101 itr->second.func(this); 88 itr->second.func(this);
@@ -108,37 +95,18 @@ protected:
108 /** 95 /**
109 * Registers the functions in the service 96 * Registers the functions in the service
110 */ 97 */
111 void Register(const FunctionInfo* functions, int len) { 98 template <size_t N>
112 for (int i = 0; i < len; i++) { 99 void Register(const FunctionInfo (&functions)[N]) {
113 m_functions[functions[i].id] = functions[i]; 100 m_functions.reserve(N);
101 for (auto& fn : functions) {
102 // Usually this array is sorted by id already, so hint to instead at the end
103 m_functions.emplace_hint(m_functions.cend(), fn.id, fn);
114 } 104 }
115 } 105 }
116 106
117private: 107private:
108 boost::container::flat_map<u32, FunctionInfo> m_functions;
118 109
119 std::vector<Handle> m_handles;
120 std::map<u32, FunctionInfo> m_functions;
121
122};
123
124/// Simple class to manage accessing services from ports and UID handles
125class Manager {
126public:
127 /// Add a service to the manager
128 void AddService(Interface* service);
129
130 /// Removes a service from the manager
131 void DeleteService(const std::string& port_name);
132
133 /// Get a Service Interface from its Handle
134 Interface* FetchFromHandle(Handle handle);
135
136 /// Get a Service Interface from its port
137 Interface* FetchFromPortName(const std::string& port_name);
138
139private:
140 std::vector<Interface*> m_services;
141 std::map<std::string, u32> m_port_map;
142}; 110};
143 111
144/// Initialize ServiceManager 112/// Initialize ServiceManager
@@ -147,8 +115,9 @@ void Init();
147/// Shutdown ServiceManager 115/// Shutdown ServiceManager
148void Shutdown(); 116void Shutdown();
149 117
150 118/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
151extern Manager* g_manager; ///< Service manager 119extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
152 120/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
121extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
153 122
154} // namespace 123} // namespace
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index bb8ee86be..414c53c54 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -734,7 +734,7 @@ const Interface::FunctionInfo FunctionTable[] = {
734// Interface class 734// Interface class
735 735
736Interface::Interface() { 736Interface::Interface() {
737 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 737 Register(FunctionTable);
738} 738}
739 739
740Interface::~Interface() { 740Interface::~Interface() {
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index aa0aac3bb..cc59a03ce 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -23,7 +23,7 @@ static void GetProcSemaphore(Service::Interface* self) {
23 u32* cmd_buff = Kernel::GetCommandBuffer(); 23 u32* cmd_buff = Kernel::GetCommandBuffer();
24 24
25 // TODO(bunnei): Change to a semaphore once these have been implemented 25 // TODO(bunnei): Change to a semaphore once these have been implemented
26 event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom(); 26 event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event");
27 event_handle->Clear(); 27 event_handle->Clear();
28 28
29 cmd_buff[1] = 0; // No error 29 cmd_buff[1] = 0; // No error
@@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) {
35 u32* cmd_buff = Kernel::GetCommandBuffer(); 35 u32* cmd_buff = Kernel::GetCommandBuffer();
36 36
37 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); 37 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
38 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 38 auto it = Service::g_srv_services.find(port_name);
39 39
40 if (nullptr != service) { 40 if (it != Service::g_srv_services.end()) {
41 cmd_buff[3] = service->GetHandle(); 41 cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom();
42 LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); 42 LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
43 } else { 43 } else {
44 LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); 44 LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
@@ -63,7 +63,7 @@ const Interface::FunctionInfo FunctionTable[] = {
63// Interface class 63// Interface class
64 64
65Interface::Interface() { 65Interface::Interface() {
66 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 66 Register(FunctionTable);
67} 67}
68 68
69} // namespace 69} // namespace
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index 360516cdf..3f49c1c97 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
22// Interface class 22// Interface class
23 23
24Interface::Interface() { 24Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable);
26} 26}
27 27
28} // namespace 28} // namespace
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index b3d873ef0..fc76d2721 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -54,7 +54,7 @@ const Interface::FunctionInfo FunctionTable[] = {
54// Interface class 54// Interface class
55 55
56Interface::Interface() { 56Interface::Interface() {
57 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 57 Register(FunctionTable);
58} 58}
59 59
60} // namespace 60} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 88813c2ce..34a27917f 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE;
30 30
31namespace SVC { 31namespace SVC {
32 32
33const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
34 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
35const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
36 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
37
33/// An invalid result code that is meant to be overwritten when a thread resumes from waiting 38/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
34const ResultCode RESULT_INVALID(0xDEADC0DE); 39const ResultCode RESULT_INVALID(0xDEADC0DE);
35 40
@@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
94} 99}
95 100
96/// Connect to an OS service given the port name, returns the handle to the port to out 101/// Connect to an OS service given the port name, returns the handle to the port to out
97static ResultCode ConnectToPort(Handle* out, const char* port_name) { 102static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
98 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 103 if (port_name == nullptr)
104 return ERR_NOT_FOUND;
105 if (std::strlen(port_name) > 11)
106 return ERR_PORT_NAME_TOO_LONG;
99 107
100 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 108 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
101 _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
102 109
103 *out = service->GetHandle(); 110 auto it = Service::g_kernel_named_ports.find(port_name);
111 if (it == Service::g_kernel_named_ports.end()) {
112 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name);
113 return ERR_NOT_FOUND;
114 }
104 115
116 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second));
105 return RESULT_SUCCESS; 117 return RESULT_SUCCESS;
106} 118}
107 119
@@ -119,9 +131,8 @@ static ResultCode SendSyncRequest(Handle handle) {
119 131
120/// Close a handle 132/// Close a handle
121static ResultCode CloseHandle(Handle handle) { 133static ResultCode CloseHandle(Handle handle) {
122 // ImplementMe 134 LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
123 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); 135 return Kernel::g_handle_table.Close(handle);
124 return RESULT_SUCCESS;
125} 136}
126 137
127/// Wait for a handle to synchronize, timeout after the specified nanoseconds 138/// Wait for a handle to synchronize, timeout after the specified nanoseconds
@@ -140,7 +151,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
140 Kernel::WaitCurrentThread_WaitSynchronization(object, false, false); 151 Kernel::WaitCurrentThread_WaitSynchronization(object, false, false);
141 152
142 // Create an event to wake the thread up after the specified nanosecond delay has passed 153 // Create an event to wake the thread up after the specified nanosecond delay has passed
143 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); 154 Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
144 155
145 HLE::Reschedule(__func__); 156 HLE::Reschedule(__func__);
146 157
@@ -216,7 +227,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
216 } 227 }
217 228
218 // Create an event to wake the thread up after the specified nanosecond delay has passed 229 // Create an event to wake the thread up after the specified nanosecond delay has passed
219 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); 230 Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
220 231
221 HLE::Reschedule(__func__); 232 HLE::Reschedule(__func__);
222 233
@@ -250,7 +261,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
250static ResultCode CreateAddressArbiter(Handle* out_handle) { 261static ResultCode CreateAddressArbiter(Handle* out_handle) {
251 using Kernel::AddressArbiter; 262 using Kernel::AddressArbiter;
252 263
253 CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create()); 264 SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create();
254 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter))); 265 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter)));
255 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle); 266 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle);
256 return RESULT_SUCCESS; 267 return RESULT_SUCCESS;
@@ -355,7 +366,7 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) {
355static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { 366static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
356 using Kernel::Mutex; 367 using Kernel::Mutex;
357 368
358 CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0)); 369 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
359 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 370 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
360 371
361 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 372 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) {
423 434
424/// Create an event 435/// Create an event
425static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { 436static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
426 CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type))); 437 using Kernel::Event;
438
439 SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type));
427 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 440 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
428 441
429 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 442 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) {
433 446
434/// Duplicates a kernel handle 447/// Duplicates a kernel handle
435static ResultCode DuplicateHandle(Handle* out, Handle handle) { 448static ResultCode DuplicateHandle(Handle* out, Handle handle) {
436 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); 449 CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle));
437 if (out_h.Succeeded()) { 450 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
438 *out = *out_h; 451 return RESULT_SUCCESS;
439 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
440 }
441 return out_h.Code();
442} 452}
443 453
444/// Signals an event 454/// Signals an event
445static ResultCode SignalEvent(Handle handle) { 455static ResultCode SignalEvent(Handle handle) {
456 using Kernel::Event;
446 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); 457 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
447 458
448 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); 459 SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
449 if (evt == nullptr) 460 if (evt == nullptr)
450 return ERR_INVALID_HANDLE; 461 return ERR_INVALID_HANDLE;
451 462
@@ -456,9 +467,10 @@ static ResultCode SignalEvent(Handle handle) {
456 467
457/// Clears an event 468/// Clears an event
458static ResultCode ClearEvent(Handle handle) { 469static ResultCode ClearEvent(Handle handle) {
470 using Kernel::Event;
459 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); 471 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
460 472
461 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); 473 SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
462 if (evt == nullptr) 474 if (evt == nullptr)
463 return ERR_INVALID_HANDLE; 475 return ERR_INVALID_HANDLE;
464 476
@@ -470,7 +482,7 @@ static ResultCode ClearEvent(Handle handle) {
470static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { 482static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
471 using Kernel::Timer; 483 using Kernel::Timer;
472 484
473 CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type))); 485 SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type));
474 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 486 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
475 487
476 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 488 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
@@ -528,7 +540,7 @@ static void SleepThread(s64 nanoseconds) {
528 Kernel::WaitCurrentThread_Sleep(); 540 Kernel::WaitCurrentThread_Sleep();
529 541
530 // Create an event to wake the thread up after the specified nanosecond delay has passed 542 // Create an event to wake the thread up after the specified nanosecond delay has passed
531 Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); 543 Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds);
532 544
533 HLE::Reschedule(__func__); 545 HLE::Reschedule(__func__);
534} 546}
@@ -544,7 +556,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
544 using Kernel::SharedMemory; 556 using Kernel::SharedMemory;
545 // TODO(Subv): Implement this function 557 // TODO(Subv): Implement this function
546 558
547 CASCADE_RESULT(auto shared_memory, SharedMemory::Create()); 559 SharedPtr<SharedMemory> shared_memory = SharedMemory::Create();
548 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 560 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
549 561
550 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 562 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);