summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar bunnei2014-12-28 21:11:55 -0500
committerGravatar bunnei2014-12-28 21:11:55 -0500
commit77363d9590ed544cf714f26c575e98b7858e18e1 (patch)
treea48225a3b62bb3d72d94289b6e34326cbed4f5cc /src/core/hle/kernel
parentMerge pull request #357 from bunnei/dyncom-pkhbt-pkhtb (diff)
parentKernel: New handle manager (diff)
downloadyuzu-77363d9590ed544cf714f26c575e98b7858e18e1.tar.gz
yuzu-77363d9590ed544cf714f26c575e98b7858e18e1.tar.xz
yuzu-77363d9590ed544cf714f26c575e98b7858e18e1.zip
Merge pull request #331 from yuriks/handle-reform
New Handle manager
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp7
-rw-r--r--src/core/hle/kernel/event.cpp15
-rw-r--r--src/core/hle/kernel/kernel.cpp124
-rw-r--r--src/core/hle/kernel/kernel.h196
-rw-r--r--src/core/hle/kernel/mutex.cpp11
-rw-r--r--src/core/hle/kernel/semaphore.cpp9
-rw-r--r--src/core/hle/kernel/session.h4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp11
-rw-r--r--src/core/hle/kernel/thread.cpp27
-rw-r--r--src/core/hle/kernel/thread.h3
10 files changed, 227 insertions, 180 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 77491900a..38705e3cd 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -20,8 +20,8 @@ public:
20 std::string GetTypeName() const override { return "Arbiter"; } 20 std::string GetTypeName() const override { return "Arbiter"; }
21 std::string GetName() const override { return name; } 21 std::string GetName() const override { return name; }
22 22
23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; } 23 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
24 Kernel::HandleType GetHandleType() const override { return HandleType::AddressArbiter; } 24 HandleType GetHandleType() const override { return HANDLE_TYPE; }
25 25
26 std::string name; ///< Name of address arbiter object (optional) 26 std::string name; ///< Name of address arbiter object (optional)
27}; 27};
@@ -62,7 +62,8 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
62/// Create an address arbiter 62/// Create an address arbiter
63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { 63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
64 AddressArbiter* address_arbiter = new AddressArbiter; 64 AddressArbiter* address_arbiter = new AddressArbiter;
65 handle = Kernel::g_object_pool.Create(address_arbiter); 65 // TOOD(yuriks): Fix error reporting
66 handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
66 address_arbiter->name = name; 67 address_arbiter->name = name;
67 return address_arbiter; 68 return address_arbiter;
68} 69}
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 4de3fab3c..e43c3ee4e 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -19,8 +19,8 @@ public:
19 std::string GetTypeName() const override { return "Event"; } 19 std::string GetTypeName() const override { return "Event"; }
20 std::string GetName() const override { return name; } 20 std::string GetName() const override { return name; }
21 21
22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } 22 static const HandleType HANDLE_TYPE = HandleType::Event;
23 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Event; } 23 HandleType GetHandleType() const override { return HANDLE_TYPE; }
24 24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
@@ -53,7 +53,7 @@ public:
53 * @return Result of operation, 0 on success, otherwise error code 53 * @return Result of operation, 0 on success, otherwise error code
54 */ 54 */
55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { 55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
56 Event* evt = g_object_pool.Get<Event>(handle); 56 Event* evt = g_handle_table.Get<Event>(handle);
57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
58 58
59 evt->permanent_locked = permanent_locked; 59 evt->permanent_locked = permanent_locked;
@@ -67,7 +67,7 @@ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
67 * @return Result of operation, 0 on success, otherwise error code 67 * @return Result of operation, 0 on success, otherwise error code
68 */ 68 */
69ResultCode SetEventLocked(const Handle handle, const bool locked) { 69ResultCode SetEventLocked(const Handle handle, const bool locked) {
70 Event* evt = g_object_pool.Get<Event>(handle); 70 Event* evt = g_handle_table.Get<Event>(handle);
71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
72 72
73 if (!evt->permanent_locked) { 73 if (!evt->permanent_locked) {
@@ -82,7 +82,7 @@ ResultCode SetEventLocked(const Handle handle, const bool locked) {
82 * @return Result of operation, 0 on success, otherwise error code 82 * @return Result of operation, 0 on success, otherwise error code
83 */ 83 */
84ResultCode SignalEvent(const Handle handle) { 84ResultCode SignalEvent(const Handle handle) {
85 Event* evt = g_object_pool.Get<Event>(handle); 85 Event* evt = g_handle_table.Get<Event>(handle);
86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
87 87
88 // Resume threads waiting for event to signal 88 // Resume threads waiting for event to signal
@@ -110,7 +110,7 @@ ResultCode SignalEvent(const Handle handle) {
110 * @return Result of operation, 0 on success, otherwise error code 110 * @return Result of operation, 0 on success, otherwise error code
111 */ 111 */
112ResultCode ClearEvent(Handle handle) { 112ResultCode ClearEvent(Handle handle) {
113 Event* evt = g_object_pool.Get<Event>(handle); 113 Event* evt = g_handle_table.Get<Event>(handle);
114 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 114 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
115 115
116 if (!evt->permanent_locked) { 116 if (!evt->permanent_locked) {
@@ -129,7 +129,8 @@ ResultCode ClearEvent(Handle handle) {
129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { 129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
130 Event* evt = new Event; 130 Event* evt = new Event;
131 131
132 handle = Kernel::g_object_pool.Create(evt); 132 // TOOD(yuriks): Fix error reporting
133 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE);
133 134
134 evt->locked = true; 135 evt->locked = true;
135 evt->permanent_locked = false; 136 evt->permanent_locked = false;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 5fd06046e..e59ed1b57 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -13,77 +13,93 @@
13namespace Kernel { 13namespace Kernel {
14 14
15Handle g_main_thread = 0; 15Handle g_main_thread = 0;
16ObjectPool g_object_pool; 16HandleTable g_handle_table;
17u64 g_program_id = 0; 17u64 g_program_id = 0;
18 18
19ObjectPool::ObjectPool() { 19HandleTable::HandleTable() {
20 next_id = INITIAL_NEXT_ID; 20 next_generation = 1;
21 Clear();
21} 22}
22 23
23Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) { 24ResultVal<Handle> HandleTable::Create(Object* obj) {
24 if (range_top > MAX_COUNT) { 25 _dbg_assert_(Kernel, obj != nullptr);
25 range_top = MAX_COUNT; 26
26 } 27 u16 slot = next_free_slot;
27 if (next_id >= range_bottom && next_id < range_top) { 28 if (slot >= generations.size()) {
28 range_bottom = next_id++; 29 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
29 } 30 return ERR_OUT_OF_HANDLES;
30 for (int i = range_bottom; i < range_top; i++) {
31 if (!occupied[i]) {
32 occupied[i] = true;
33 pool[i] = obj;
34 pool[i]->handle = i + HANDLE_OFFSET;
35 return i + HANDLE_OFFSET;
36 }
37 } 31 }
38 LOG_ERROR(Kernel, "Unable to allocate kernel object, too many objects slots in use."); 32 next_free_slot = generations[slot];
39 return 0;
40}
41 33
42bool ObjectPool::IsValid(Handle handle) const { 34 u16 generation = next_generation++;
43 int index = handle - HANDLE_OFFSET;
44 if (index < 0)
45 return false;
46 if (index >= MAX_COUNT)
47 return false;
48 35
49 return occupied[index]; 36 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
37 // CTR-OS doesn't use generation 0, so skip straight to 1.
38 if (next_generation >= (1 << 15)) next_generation = 1;
39
40 generations[slot] = generation;
41 intrusive_ptr_add_ref(obj);
42 objects[slot] = obj;
43
44 Handle handle = generation | (slot << 15);
45 obj->handle = handle;
46 return MakeResult<Handle>(handle);
50} 47}
51 48
52void ObjectPool::Clear() { 49ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
53 for (int i = 0; i < MAX_COUNT; i++) { 50 Object* object = GetGeneric(handle);
54 //brutally clear everything, no validation 51 if (object == nullptr) {
55 if (occupied[i]) 52 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
56 delete pool[i]; 53 return ERR_INVALID_HANDLE;
57 occupied[i] = false;
58 } 54 }
59 pool.fill(nullptr); 55 return Create(object);
60 next_id = INITIAL_NEXT_ID;
61} 56}
62 57
63Object* &ObjectPool::operator [](Handle handle) 58ResultCode HandleTable::Close(Handle handle) {
64{ 59 if (!IsValid(handle))
65 _dbg_assert_msg_(Kernel, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); 60 return ERR_INVALID_HANDLE;
66 return pool[handle - HANDLE_OFFSET]; 61
62 size_t slot = GetSlot(handle);
63 u16 generation = GetGeneration(handle);
64
65 intrusive_ptr_release(objects[slot]);
66 objects[slot] = nullptr;
67
68 generations[generation] = next_free_slot;
69 next_free_slot = slot;
70 return RESULT_SUCCESS;
67} 71}
68 72
69void ObjectPool::List() { 73bool HandleTable::IsValid(Handle handle) const {
70 for (int i = 0; i < MAX_COUNT; i++) { 74 size_t slot = GetSlot(handle);
71 if (occupied[i]) { 75 u16 generation = GetGeneration(handle);
72 if (pool[i]) { 76
73 LOG_DEBUG(Kernel, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), 77 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
74 pool[i]->GetName().c_str());
75 }
76 }
77 }
78} 78}
79 79
80int ObjectPool::GetCount() const { 80Object* HandleTable::GetGeneric(Handle handle) const {
81 return std::count(occupied.begin(), occupied.end(), true); 81 if (handle == CurrentThread) {
82 // TODO(yuriks) Directly return the pointer once this is possible.
83 handle = GetCurrentThreadHandle();
84 } else if (handle == CurrentProcess) {
85 LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
86 return nullptr;
87 }
88
89 if (!IsValid(handle)) {
90 return nullptr;
91 }
92 return objects[GetSlot(handle)];
82} 93}
83 94
84Object* ObjectPool::CreateByIDType(int type) { 95void HandleTable::Clear() {
85 LOG_ERROR(Kernel, "Unimplemented: %d.", type); 96 for (size_t i = 0; i < MAX_COUNT; ++i) {
86 return nullptr; 97 generations[i] = i + 1;
98 if (objects[i] != nullptr)
99 intrusive_ptr_release(objects[i]);
100 objects[i] = nullptr;
101 }
102 next_free_slot = 0;
87} 103}
88 104
89/// Initialize the kernel 105/// Initialize the kernel
@@ -95,7 +111,7 @@ void Init() {
95void Shutdown() { 111void Shutdown() {
96 Kernel::ThreadingShutdown(); 112 Kernel::ThreadingShutdown();
97 113
98 g_object_pool.Clear(); // Free all kernel objects 114 g_handle_table.Clear(); // Free all kernel objects
99} 115}
100 116
101/** 117/**
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 32258d5a0..7f86fd07d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -12,13 +12,17 @@
12typedef u32 Handle; 12typedef u32 Handle;
13typedef s32 Result; 13typedef s32 Result;
14 14
15const Handle INVALID_HANDLE = 0;
16
15namespace Kernel { 17namespace Kernel {
16 18
17// From kernel.h. Declarations duplicated here to avoid a circular header dependency. 19// TODO: Verify code
18class Thread; 20const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
19Thread* GetCurrentThread(); 21 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
22// TOOD: Verify code
23const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
20 24
21enum KernelHandle { 25enum KernelHandle : Handle {
22 CurrentThread = 0xFFFF8000, 26 CurrentThread = 0xFFFF8000,
23 CurrentProcess = 0xFFFF8001, 27 CurrentProcess = 0xFFFF8001,
24}; 28};
@@ -41,10 +45,10 @@ enum {
41 DEFAULT_STACK_SIZE = 0x4000, 45 DEFAULT_STACK_SIZE = 0x4000,
42}; 46};
43 47
44class ObjectPool; 48class HandleTable;
45 49
46class Object : NonCopyable { 50class Object : NonCopyable {
47 friend class ObjectPool; 51 friend class HandleTable;
48 u32 handle; 52 u32 handle;
49public: 53public:
50 virtual ~Object() {} 54 virtual ~Object() {}
@@ -61,106 +65,130 @@ public:
61 LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); 65 LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
62 return UnimplementedFunction(ErrorModule::Kernel); 66 return UnimplementedFunction(ErrorModule::Kernel);
63 } 67 }
64};
65 68
66class ObjectPool : NonCopyable { 69private:
67public: 70 friend void intrusive_ptr_add_ref(Object*);
68 ObjectPool(); 71 friend void intrusive_ptr_release(Object*);
69 ~ObjectPool() {}
70 72
71 // Allocates a handle within the range and inserts the object into the map. 73 unsigned int ref_count = 0;
72 Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); 74};
73 75
74 static Object* CreateByIDType(int type); 76// Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting
77inline void intrusive_ptr_add_ref(Object* object) {
78 ++object->ref_count;
79}
75 80
76 template <class T> 81inline void intrusive_ptr_release(Object* object) {
77 void Destroy(Handle handle) { 82 if (--object->ref_count == 0) {
78 if (Get<T>(handle)) { 83 delete object;
79 occupied[handle - HANDLE_OFFSET] = false;
80 delete pool[handle - HANDLE_OFFSET];
81 }
82 } 84 }
85}
83 86
84 bool IsValid(Handle handle) const; 87/**
88 * This class allows the creation of Handles, which are references to objects that can be tested
89 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
90 * emulated process. it has been designed so that it follows the same handle format and has
91 * approximately the same restrictions as the handle manager in the CTR-OS.
92 *
93 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
94 * The slot index is used to index into the arrays in this class to access the data corresponding
95 * to the Handle.
96 *
97 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
98 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
99 * value of the counter is stored into the Handle as well as in the handle table (in the
100 * "generations" array). When looking up a handle, the Handle's generation must match with the
101 * value stored on the class, otherwise the Handle is considered invalid.
102 *
103 * To find free slots when allocating a Handle without needing to scan the entire object array, the
104 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
105 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
106 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
107 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
108 * verified and isn't likely to cause any problems.
109 */
110class HandleTable final : NonCopyable {
111public:
112 HandleTable();
85 113
86 template <class T> 114 /**
87 T* Get(Handle handle) { 115 * Allocates a handle for the given object.
88 if (handle == CurrentThread) { 116 * @return The created Handle or one of the following errors:
89 return reinterpret_cast<T*>(GetCurrentThread()); 117 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
90 } 118 */
119 ResultVal<Handle> Create(Object* obj);
91 120
92 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 121 /**
93 if (handle != 0) { 122 * Returns a new handle that points to the same object as the passed in handle.
94 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 123 * @return The duplicated Handle or one of the following errors:
95 } 124 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
96 return nullptr; 125 * - Any errors returned by `Create()`.
97 } else { 126 */
98 Object* t = pool[handle - HANDLE_OFFSET]; 127 ResultVal<Handle> Duplicate(Handle handle);
99 if (t->GetHandleType() != T::GetStaticHandleType()) {
100 LOG_ERROR(Kernel, "Wrong object type for %08x", handle);
101 return nullptr;
102 }
103 return static_cast<T*>(t);
104 }
105 }
106 128
107 // ONLY use this when you know the handle is valid. 129 /**
108 template <class T> 130 * Closes a handle, removing it from the table and decreasing the object's ref-count.
109 T *GetFast(Handle handle) { 131 * @return `RESULT_SUCCESS` or one of the following errors:
110 if (handle == CurrentThread) { 132 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
111 return reinterpret_cast<T*>(GetCurrentThread()); 133 */
112 } 134 ResultCode Close(Handle handle);
113 135
114 const Handle realHandle = handle - HANDLE_OFFSET; 136 /// Checks if a handle is valid and points to an existing object.
115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 137 bool IsValid(Handle handle) const;
116 return static_cast<T*>(pool[realHandle]);
117 }
118 138
119 template <class T, typename ArgT> 139 /**
120 void Iterate(bool func(T*, ArgT), ArgT arg) { 140 * Looks up a handle.
121 int type = T::GetStaticIDType(); 141 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
122 for (int i = 0; i < MAX_COUNT; i++) 142 */
123 { 143 Object* GetGeneric(Handle handle) const;
124 if (!occupied[i])
125 continue;
126 T* t = static_cast<T*>(pool[i]);
127 if (t->GetIDType() == type) {
128 if (!func(t, arg))
129 break;
130 }
131 }
132 }
133 144
134 bool GetIDType(Handle handle, HandleType* type) const { 145 /**
135 if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || 146 * Looks up a handle while verifying its type.
136 !occupied[handle - HANDLE_OFFSET]) { 147 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
137 LOG_ERROR(Kernel, "Bad object handle %08X", handle); 148 * type differs from the handle type `T::HANDLE_TYPE`.
138 return false; 149 */
150 template <class T>
151 T* Get(Handle handle) const {
152 Object* object = GetGeneric(handle);
153 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
154 return static_cast<T*>(object);
139 } 155 }
140 Object* t = pool[handle - HANDLE_OFFSET]; 156 return nullptr;
141 *type = t->GetHandleType();
142 return true;
143 } 157 }
144 158
145 Object* &operator [](Handle handle); 159 /// Closes all handles held in this table.
146 void List();
147 void Clear(); 160 void Clear();
148 int GetCount() const;
149 161
150private: 162private:
163 /**
164 * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
165 * reduced by ExHeader values, but this is not emulated here.
166 */
167 static const size_t MAX_COUNT = 4096;
168
169 static size_t GetSlot(Handle handle) { return handle >> 15; }
170 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; }
171
172 /// Stores the Object referenced by the handle or null if the slot is empty.
173 std::array<Object*, MAX_COUNT> objects;
151 174
152 enum { 175 /**
153 MAX_COUNT = 0x1000, 176 * The value of `next_generation` when the handle was created, used to check for validity. For
154 HANDLE_OFFSET = 0x100, 177 * empty slots, contains the index of the next free slot in the list.
155 INITIAL_NEXT_ID = 0x10, 178 */
156 }; 179 std::array<u16, MAX_COUNT> generations;
180
181 /**
182 * Global counter of the number of created handles. Stored in `generations` when a handle is
183 * created, and wraps around to 1 when it hits 0x8000.
184 */
185 u16 next_generation;
157 186
158 std::array<Object*, MAX_COUNT> pool; 187 /// Head of the free slots linked list.
159 std::array<bool, MAX_COUNT> occupied; 188 u16 next_free_slot;
160 int next_id;
161}; 189};
162 190
163extern ObjectPool g_object_pool; 191extern HandleTable g_handle_table;
164extern Handle g_main_thread; 192extern Handle g_main_thread;
165 193
166/// The ID code of the currently running game 194/// The ID code of the currently running game
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 5a18af114..558068c79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -18,8 +18,8 @@ public:
18 std::string GetTypeName() const override { return "Mutex"; } 18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; } 19 std::string GetName() const override { return name; }
20 20
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } 21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; } 22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23 23
24 bool initial_locked; ///< Initial lock state when mutex was created 24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state 25 bool locked; ///< Current locked state
@@ -87,7 +87,7 @@ void ReleaseThreadMutexes(Handle thread) {
87 87
88 // Release every mutex that the thread holds, and resume execution on the waiting threads 88 // Release every mutex that the thread holds, and resume execution on the waiting threads
89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
90 Mutex* mutex = g_object_pool.GetFast<Mutex>(iter->second); 90 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second);
91 ResumeWaitingThread(mutex); 91 ResumeWaitingThread(mutex);
92 } 92 }
93 93
@@ -115,7 +115,7 @@ bool ReleaseMutex(Mutex* mutex) {
115 * @param handle Handle to mutex to release 115 * @param handle Handle to mutex to release
116 */ 116 */
117ResultCode ReleaseMutex(Handle handle) { 117ResultCode ReleaseMutex(Handle handle) {
118 Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle); 118 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle);
119 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); 119 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
120 120
121 if (!ReleaseMutex(mutex)) { 121 if (!ReleaseMutex(mutex)) {
@@ -136,7 +136,8 @@ ResultCode ReleaseMutex(Handle handle) {
136 */ 136 */
137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { 137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
138 Mutex* mutex = new Mutex; 138 Mutex* mutex = new Mutex;
139 handle = Kernel::g_object_pool.Create(mutex); 139 // TODO(yuriks): Fix error reporting
140 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
140 141
141 mutex->locked = mutex->initial_locked = initial_locked; 142 mutex->locked = mutex->initial_locked = initial_locked;
142 mutex->name = name; 143 mutex->name = name;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index b81d0b26a..6bc8066a6 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -17,8 +17,8 @@ public:
17 std::string GetTypeName() const override { return "Semaphore"; } 17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; } 18 std::string GetName() const override { return name; }
19 19
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22 22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 s32 available_count; ///< Number of free slots left in the semaphore 24 s32 available_count; ///< Number of free slots left in the semaphore
@@ -57,7 +57,8 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
57 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 57 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
58 58
59 Semaphore* semaphore = new Semaphore; 59 Semaphore* semaphore = new Semaphore;
60 *handle = g_object_pool.Create(semaphore); 60 // TOOD(yuriks): Fix error reporting
61 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE);
61 62
62 // When the semaphore is created, some slots are reserved for other threads, 63 // When the semaphore is created, some slots are reserved for other threads,
63 // and the rest is reserved for the caller thread 64 // and the rest is reserved for the caller thread
@@ -69,7 +70,7 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
69} 70}
70 71
71ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 72ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
72 Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle); 73 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle);
73 if (semaphore == nullptr) 74 if (semaphore == nullptr)
74 return InvalidHandle(ErrorModule::Kernel); 75 return InvalidHandle(ErrorModule::Kernel);
75 76
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 6760f346e..91f3ffc2c 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -45,8 +45,8 @@ class Session : public Object {
45public: 45public:
46 std::string GetTypeName() const override { return "Session"; } 46 std::string GetTypeName() const override { return "Session"; }
47 47
48 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Session; } 48 static const HandleType HANDLE_TYPE = HandleType::Session;
49 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Session; } 49 HandleType GetHandleType() const override { return HANDLE_TYPE; }
50 50
51 /** 51 /**
52 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 52 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 2840f13bb..cea1f6fa1 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -13,8 +13,8 @@ class SharedMemory : public Object {
13public: 13public:
14 std::string GetTypeName() const override { return "SharedMemory"; } 14 std::string GetTypeName() const override { return "SharedMemory"; }
15 15
16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } 16 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } 17 HandleType GetHandleType() const override { return HANDLE_TYPE; }
18 18
19 u32 base_address; ///< Address of shared memory block in RAM 19 u32 base_address; ///< Address of shared memory block in RAM
20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
@@ -32,7 +32,8 @@ public:
32 */ 32 */
33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { 33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
34 SharedMemory* shared_memory = new SharedMemory; 34 SharedMemory* shared_memory = new SharedMemory;
35 handle = Kernel::g_object_pool.Create(shared_memory); 35 // TOOD(yuriks): Fix error reporting
36 handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
36 shared_memory->name = name; 37 shared_memory->name = name;
37 return shared_memory; 38 return shared_memory;
38} 39}
@@ -60,7 +61,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions
60 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
61 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
62 } 63 }
63 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); 64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
64 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
65 66
66 shared_memory->base_address = address; 67 shared_memory->base_address = address;
@@ -71,7 +72,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions
71} 72}
72 73
73ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { 74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
74 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); 75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
75 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
76 77
77 if (0 != shared_memory->base_address) 78 if (0 != shared_memory->base_address)
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index c6a8dc7b9..872df2d14 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -26,8 +26,8 @@ public:
26 std::string GetName() const override { return name; } 26 std::string GetName() const override { return name; }
27 std::string GetTypeName() const override { return "Thread"; } 27 std::string GetTypeName() const override { return "Thread"; }
28 28
29 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } 29 static const HandleType HANDLE_TYPE = HandleType::Thread;
30 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Thread; } 30 HandleType GetHandleType() const override { return HANDLE_TYPE; }
31 31
32 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } 32 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
33 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } 33 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
@@ -164,7 +164,7 @@ static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handl
164 164
165/// Stops the current thread 165/// Stops the current thread
166ResultCode StopThread(Handle handle, const char* reason) { 166ResultCode StopThread(Handle handle, const char* reason) {
167 Thread* thread = g_object_pool.Get<Thread>(handle); 167 Thread* thread = g_handle_table.Get<Thread>(handle);
168 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 168 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
169 169
170 // Release all the mutexes that this thread holds 170 // Release all the mutexes that this thread holds
@@ -173,7 +173,7 @@ ResultCode StopThread(Handle handle, const char* reason) {
173 ChangeReadyState(thread, false); 173 ChangeReadyState(thread, false);
174 thread->status = THREADSTATUS_DORMANT; 174 thread->status = THREADSTATUS_DORMANT;
175 for (Handle waiting_handle : thread->waiting_threads) { 175 for (Handle waiting_handle : thread->waiting_threads) {
176 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); 176 Thread* waiting_thread = g_handle_table.Get<Thread>(waiting_handle);
177 177
178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle)) 178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle))
179 ResumeThreadFromWait(waiting_handle); 179 ResumeThreadFromWait(waiting_handle);
@@ -210,7 +210,7 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
210 210
211 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 211 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
212 for (Handle handle : thread_queue) { 212 for (Handle handle : thread_queue) {
213 Thread* thread = g_object_pool.Get<Thread>(handle); 213 Thread* thread = g_handle_table.Get<Thread>(handle);
214 214
215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
216 continue; 216 continue;
@@ -235,7 +235,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
235 235
236 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 236 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
237 for (Handle handle : thread_queue) { 237 for (Handle handle : thread_queue) {
238 Thread* thread = g_object_pool.Get<Thread>(handle); 238 Thread* thread = g_handle_table.Get<Thread>(handle);
239 239
240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
241 ResumeThreadFromWait(handle); 241 ResumeThreadFromWait(handle);
@@ -288,7 +288,7 @@ Thread* NextThread() {
288 if (next == 0) { 288 if (next == 0) {
289 return nullptr; 289 return nullptr;
290 } 290 }
291 return Kernel::g_object_pool.Get<Thread>(next); 291 return Kernel::g_handle_table.Get<Thread>(next);
292} 292}
293 293
294void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { 294void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
@@ -305,7 +305,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_addres
305 305
306/// Resumes a thread from waiting by marking it as "ready" 306/// Resumes a thread from waiting by marking it as "ready"
307void ResumeThreadFromWait(Handle handle) { 307void ResumeThreadFromWait(Handle handle) {
308 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); 308 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
309 if (thread) { 309 if (thread) {
310 thread->status &= ~THREADSTATUS_WAIT; 310 thread->status &= ~THREADSTATUS_WAIT;
311 thread->wait_handle = 0; 311 thread->wait_handle = 0;
@@ -341,7 +341,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
341 341
342 Thread* thread = new Thread; 342 Thread* thread = new Thread;
343 343
344 handle = Kernel::g_object_pool.Create(thread); 344 // TOOD(yuriks): Fix error reporting
345 handle = Kernel::g_handle_table.Create(thread).ValueOr(INVALID_HANDLE);
345 346
346 thread_queue.push_back(handle); 347 thread_queue.push_back(handle);
347 thread_ready_queue.prepare(priority); 348 thread_ready_queue.prepare(priority);
@@ -398,7 +399,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
398 399
399/// Get the priority of the thread specified by handle 400/// Get the priority of the thread specified by handle
400ResultVal<u32> GetThreadPriority(const Handle handle) { 401ResultVal<u32> GetThreadPriority(const Handle handle) {
401 Thread* thread = g_object_pool.Get<Thread>(handle); 402 Thread* thread = g_handle_table.Get<Thread>(handle);
402 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 403 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
403 404
404 return MakeResult<u32>(thread->current_priority); 405 return MakeResult<u32>(thread->current_priority);
@@ -410,7 +411,7 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {
410 if (!handle) { 411 if (!handle) {
411 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? 412 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
412 } else { 413 } else {
413 thread = g_object_pool.Get<Thread>(handle); 414 thread = g_handle_table.Get<Thread>(handle);
414 if (thread == nullptr) { 415 if (thread == nullptr) {
415 return InvalidHandle(ErrorModule::Kernel); 416 return InvalidHandle(ErrorModule::Kernel);
416 } 417 }
@@ -481,7 +482,7 @@ void Reschedule() {
481 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 482 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
482 483
483 for (Handle handle : thread_queue) { 484 for (Handle handle : thread_queue) {
484 Thread* thread = g_object_pool.Get<Thread>(handle); 485 Thread* thread = g_handle_table.Get<Thread>(handle);
485 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", 486 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
486 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle); 487 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle);
487 } 488 }
@@ -497,7 +498,7 @@ void Reschedule() {
497} 498}
498 499
499ResultCode GetThreadId(u32* thread_id, Handle handle) { 500ResultCode GetThreadId(u32* thread_id, Handle handle) {
500 Thread* thread = g_object_pool.Get<Thread>(handle); 501 Thread* thread = g_handle_table.Get<Thread>(handle);
501 if (thread == nullptr) 502 if (thread == nullptr)
502 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS, 503 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
503 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 504 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9396b6b26..0e1397cd9 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -77,9 +77,6 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
77/// Arbitrate all threads currently waiting... 77/// Arbitrate all threads currently waiting...
78void ArbitrateAllThreads(u32 arbiter, u32 address); 78void ArbitrateAllThreads(u32 arbiter, u32 address);
79 79
80/// Gets the current thread
81Thread* GetCurrentThread();
82
83/// Gets the current thread handle 80/// Gets the current thread handle
84Handle GetCurrentThreadHandle(); 81Handle GetCurrentThreadHandle();
85 82