summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hle/kernel/handle_table.cpp125
-rw-r--r--src/core/hle/kernel/handle_table.h212
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp6
-rw-r--r--src/core/hle/kernel/hle_ipc.h7
-rw-r--r--src/core/hle/kernel/k_auto_object.h2
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp2
-rw-r--r--src/core/hle/kernel/k_handle_table.cpp135
-rw-r--r--src/core/hle/kernel/k_handle_table.h309
-rw-r--r--src/core/hle/kernel/k_process.cpp2
-rw-r--r--src/core/hle/kernel/k_process.h8
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h4
-rw-r--r--src/core/hle/kernel/k_server_session.cpp2
-rw-r--r--src/core/hle/kernel/k_thread.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp20
-rw-r--r--src/core/hle/kernel/kernel.h7
-rw-r--r--src/core/hle/kernel/process_capability.cpp4
-rw-r--r--src/core/hle/kernel/svc.cpp8
-rw-r--r--src/core/hle/kernel/svc_common.h15
-rw-r--r--src/core/hle/kernel/time_manager.cpp1
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.h5
22 files changed, 503 insertions, 381 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 889a2d2f8..83da30418 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -149,8 +149,6 @@ add_library(core STATIC
149 hle/kernel/svc_results.h 149 hle/kernel/svc_results.h
150 hle/kernel/global_scheduler_context.cpp 150 hle/kernel/global_scheduler_context.cpp
151 hle/kernel/global_scheduler_context.h 151 hle/kernel/global_scheduler_context.h
152 hle/kernel/handle_table.cpp
153 hle/kernel/handle_table.h
154 hle/kernel/hle_ipc.cpp 152 hle/kernel/hle_ipc.cpp
155 hle/kernel/hle_ipc.h 153 hle/kernel/hle_ipc.h
156 hle/kernel/init/init_slab_setup.cpp 154 hle/kernel/init/init_slab_setup.cpp
@@ -174,6 +172,8 @@ add_library(core STATIC
174 hle/kernel/k_condition_variable.h 172 hle/kernel/k_condition_variable.h
175 hle/kernel/k_event.cpp 173 hle/kernel/k_event.cpp
176 hle/kernel/k_event.h 174 hle/kernel/k_event.h
175 hle/kernel/k_handle_table.cpp
176 hle/kernel/k_handle_table.h
177 hle/kernel/k_light_condition_variable.h 177 hle/kernel/k_light_condition_variable.h
178 hle/kernel/k_light_lock.cpp 178 hle/kernel/k_light_lock.cpp
179 hle/kernel/k_light_lock.h 179 hle/kernel/k_light_lock.h
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
deleted file mode 100644
index 16c528f5b..000000000
--- a/src/core/hle/kernel/handle_table.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <utility>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/core.h"
9#include "core/hle/kernel/handle_table.h"
10#include "core/hle/kernel/k_process.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/svc_results.h"
15
16namespace Kernel {
17namespace {
18constexpr u16 GetSlot(Handle handle) {
19 return static_cast<u16>(handle >> 15);
20}
21
22constexpr u16 GetGeneration(Handle handle) {
23 return static_cast<u16>(handle & 0x7FFF);
24}
25} // Anonymous namespace
26
27HandleTable::HandleTable(KernelCore& kernel) : kernel{kernel} {
28 Clear();
29}
30
31HandleTable::~HandleTable() = default;
32
33ResultCode HandleTable::SetSize(s32 handle_table_size) {
34 if (static_cast<u32>(handle_table_size) > MAX_COUNT) {
35 LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT);
36 return ResultOutOfMemory;
37 }
38
39 // Values less than or equal to zero indicate to use the maximum allowable
40 // size for the handle table in the actual kernel, so we ignore the given
41 // value in that case, since we assume this by default unless this function
42 // is called.
43 if (handle_table_size > 0) {
44 table_size = static_cast<u16>(handle_table_size);
45 }
46
47 return RESULT_SUCCESS;
48}
49
50ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
51 ASSERT(obj != nullptr);
52
53 const u16 slot = next_free_slot;
54 if (slot >= table_size) {
55 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
56 return ResultOutOfHandles;
57 }
58 next_free_slot = generations[slot];
59
60 const u16 generation = next_generation++;
61
62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
63 // Horizon OS uses zero to represent an invalid handle, so skip to 1.
64 if (next_generation >= (1 << 15)) {
65 next_generation = 1;
66 }
67
68 generations[slot] = generation;
69 objects[slot] = obj;
70 obj->Open();
71
72 *out_handle = generation | (slot << 15);
73
74 return RESULT_SUCCESS;
75}
76
77ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
78 auto object = GetObject(handle);
79 if (object.IsNull()) {
80 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
81 return ResultInvalidHandle;
82 }
83
84 Handle out_handle{};
85 R_TRY(Add(&out_handle, object.GetPointerUnsafe()));
86
87 return MakeResult(out_handle);
88}
89
90bool HandleTable::Remove(Handle handle) {
91 if (!IsValid(handle)) {
92 LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle);
93 return {};
94 }
95
96 const u16 slot = GetSlot(handle);
97
98 if (objects[slot]) {
99 objects[slot]->Close();
100 }
101
102 objects[slot] = nullptr;
103
104 generations[slot] = next_free_slot;
105 next_free_slot = slot;
106
107 return true;
108}
109
110bool HandleTable::IsValid(Handle handle) const {
111 const std::size_t slot = GetSlot(handle);
112 const u16 generation = GetGeneration(handle);
113 const bool is_object_valid = (objects[slot] != nullptr);
114 return slot < table_size && is_object_valid && generations[slot] == generation;
115}
116
117void HandleTable::Clear() {
118 for (u16 i = 0; i < table_size; ++i) {
119 generations[i] = static_cast<u16>(i + 1);
120 objects[i] = nullptr;
121 }
122 next_free_slot = 0;
123}
124
125} // namespace Kernel
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
deleted file mode 100644
index 791e303d1..000000000
--- a/src/core/hle/kernel/handle_table.h
+++ /dev/null
@@ -1,212 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <cstddef>
9#include <memory>
10
11#include "common/common_types.h"
12#include "core/hle/kernel/k_auto_object.h"
13#include "core/hle/kernel/k_spin_lock.h"
14#include "core/hle/kernel/kernel.h"
15#include "core/hle/result.h"
16
17namespace Kernel {
18
19class KernelCore;
20
21enum KernelHandle : Handle {
22 InvalidHandle = 0,
23 CurrentThread = 0xFFFF8000,
24 CurrentProcess = 0xFFFF8001,
25};
26
27/**
28 * This class allows the creation of Handles, which are references to objects that can be tested
29 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
30 * emulated process. it has been designed so that it follows the same handle format and has
31 * approximately the same restrictions as the handle manager in the CTR-OS.
32 *
33 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
34 * The slot index is used to index into the arrays in this class to access the data corresponding
35 * to the Handle.
36 *
37 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
38 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
39 * value of the counter is stored into the Handle as well as in the handle table (in the
40 * "generations" array). When looking up a handle, the Handle's generation must match with the
41 * value stored on the class, otherwise the Handle is considered invalid.
42 *
43 * To find free slots when allocating a Handle without needing to scan the entire object array, the
44 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
45 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
46 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
47 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
48 * verified and isn't likely to cause any problems.
49 */
50class HandleTable final : NonCopyable {
51public:
52 /// This is the maximum limit of handles allowed per process in Horizon
53 static constexpr std::size_t MAX_COUNT = 1024;
54
55 explicit HandleTable(KernelCore& kernel);
56 ~HandleTable();
57
58 /**
59 * Sets the number of handles that may be in use at one time
60 * for this handle table.
61 *
62 * @param handle_table_size The desired size to limit the handle table to.
63 *
64 * @returns an error code indicating if initialization was successful.
65 * If initialization was not successful, then ERR_OUT_OF_MEMORY
66 * will be returned.
67 *
68 * @pre handle_table_size must be within the range [0, 1024]
69 */
70 ResultCode SetSize(s32 handle_table_size);
71
72 /**
73 * Returns a new handle that points to the same object as the passed in handle.
74 * @return The duplicated Handle or one of the following errors:
75 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
76 * - Any errors returned by `Create()`.
77 */
78 ResultVal<Handle> Duplicate(Handle handle);
79
80 /**
81 * Closes a handle, removing it from the table and decreasing the object's ref-count.
82 * @return `RESULT_SUCCESS` or one of the following errors:
83 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
84 */
85 bool Remove(Handle handle);
86
87 /// Checks if a handle is valid and points to an existing object.
88 bool IsValid(Handle handle) const;
89
90 template <typename T = KAutoObject>
91 KAutoObject* GetObjectImpl(Handle handle) const {
92 if (!IsValid(handle)) {
93 return nullptr;
94 }
95
96 auto* obj = objects[static_cast<u16>(handle >> 15)];
97 return obj->DynamicCast<T*>();
98 }
99
100 template <typename T = KAutoObject>
101 KScopedAutoObject<T> GetObject(Handle handle) const {
102 if (handle == CurrentThread) {
103 return kernel.CurrentScheduler()->GetCurrentThread()->DynamicCast<T*>();
104 } else if (handle == CurrentProcess) {
105 return kernel.CurrentProcess()->DynamicCast<T*>();
106 }
107
108 if (!IsValid(handle)) {
109 return nullptr;
110 }
111
112 auto* obj = objects[static_cast<u16>(handle >> 15)];
113 return obj->DynamicCast<T*>();
114 }
115
116 template <typename T = KAutoObject>
117 KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const {
118 if (!IsValid(handle)) {
119 return nullptr;
120 }
121 auto* obj = objects[static_cast<u16>(handle >> 15)];
122 return obj->DynamicCast<T*>();
123 }
124
125 /// Closes all handles held in this table.
126 void Clear();
127
128 // NEW IMPL
129
130 template <typename T>
131 ResultCode Add(Handle* out_handle, T* obj) {
132 static_assert(std::is_base_of<KAutoObject, T>::value);
133 return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken());
134 }
135
136 ResultCode Add(Handle* out_handle, KAutoObject* obj, u16 type);
137
138 template <typename T>
139 bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const {
140 // Try to convert and open all the handles.
141 size_t num_opened;
142 {
143 // Lock the table.
144 KScopedSpinLock lk(lock);
145 for (num_opened = 0; num_opened < num_handles; num_opened++) {
146 // Get the current handle.
147 const auto cur_handle = handles[num_opened];
148
149 // Get the object for the current handle.
150 KAutoObject* cur_object = this->GetObjectImpl(cur_handle);
151 if (cur_object == nullptr) {
152 break;
153 }
154
155 // Cast the current object to the desired type.
156 T* cur_t = cur_object->DynamicCast<T*>();
157 if (cur_t == nullptr) {
158 break;
159 }
160
161 // Open a reference to the current object.
162 cur_t->Open();
163 out[num_opened] = cur_t;
164 }
165 }
166
167 // If we converted every object, succeed.
168 if (num_opened == num_handles) {
169 return true;
170 }
171
172 // If we didn't convert entry object, close the ones we opened.
173 for (size_t i = 0; i < num_opened; i++) {
174 out[i]->Close();
175 }
176
177 return false;
178 }
179
180private:
181 /// Stores the Object referenced by the handle or null if the slot is empty.
182 std::array<KAutoObject*, MAX_COUNT> objects{};
183
184 /**
185 * The value of `next_generation` when the handle was created, used to check for validity. For
186 * empty slots, contains the index of the next free slot in the list.
187 */
188 std::array<u16, MAX_COUNT> generations;
189
190 /**
191 * The limited size of the handle table. This can be specified by process
192 * capabilities in order to restrict the overall number of handles that
193 * can be created in a process instance
194 */
195 u16 table_size = static_cast<u16>(MAX_COUNT);
196
197 /**
198 * Global counter of the number of created handles. Stored in `generations` when a handle is
199 * created, and wraps around to 1 when it hits 0x8000.
200 */
201 u16 next_generation = 1;
202
203 /// Head of the free slots linked list.
204 u16 next_free_slot = 0;
205
206 mutable KSpinLock lock;
207
208 /// Underlying kernel instance that this handle table operates under.
209 KernelCore& kernel;
210};
211
212} // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 69190286d..b505d20a6 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -14,8 +14,8 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "core/hle/ipc_helpers.h" 16#include "core/hle/ipc_helpers.h"
17#include "core/hle/kernel/handle_table.h"
18#include "core/hle/kernel/hle_ipc.h" 17#include "core/hle/kernel/hle_ipc.h"
18#include "core/hle/kernel/k_handle_table.h"
19#include "core/hle/kernel/k_process.h" 19#include "core/hle/kernel/k_process.h"
20#include "core/hle/kernel/k_readable_event.h" 20#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_scheduler.h" 21#include "core/hle/kernel/k_scheduler.h"
@@ -50,7 +50,7 @@ HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory&
50 50
51HLERequestContext::~HLERequestContext() = default; 51HLERequestContext::~HLERequestContext() = default;
52 52
53void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, 53void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf,
54 bool incoming) { 54 bool incoming) {
55 IPC::RequestParser rp(src_cmdbuf); 55 IPC::RequestParser rp(src_cmdbuf);
56 command_header = rp.PopRaw<IPC::CommandHeader>(); 56 command_header = rp.PopRaw<IPC::CommandHeader>();
@@ -163,7 +163,7 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
163 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. 163 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
164} 164}
165 165
166ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, 166ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table,
167 u32_le* src_cmdbuf) { 167 u32_le* src_cmdbuf) {
168 ParseCommandBuffer(handle_table, src_cmdbuf, true); 168 ParseCommandBuffer(handle_table, src_cmdbuf, true);
169 if (command_header->type == IPC::CommandType::Close) { 169 if (command_header->type == IPC::CommandType::Close) {
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 4b92ba655..fa031c121 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -17,6 +17,7 @@
17#include "common/swap.h" 17#include "common/swap.h"
18#include "core/hle/ipc.h" 18#include "core/hle/ipc.h"
19#include "core/hle/kernel/k_auto_object.h" 19#include "core/hle/kernel/k_auto_object.h"
20#include "core/hle/kernel/svc_common.h"
20 21
21union ResultCode; 22union ResultCode;
22 23
@@ -35,9 +36,9 @@ class ServiceFrameworkBase;
35namespace Kernel { 36namespace Kernel {
36 37
37class Domain; 38class Domain;
38class HandleTable;
39class HLERequestContext; 39class HLERequestContext;
40class KernelCore; 40class KernelCore;
41class KHandleTable;
41class KProcess; 42class KProcess;
42class KServerSession; 43class KServerSession;
43class KThread; 44class KThread;
@@ -121,7 +122,7 @@ public:
121 } 122 }
122 123
123 /// Populates this context with data from the requesting process/thread. 124 /// Populates this context with data from the requesting process/thread.
124 ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, 125 ResultCode PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table,
125 u32_le* src_cmdbuf); 126 u32_le* src_cmdbuf);
126 127
127 /// Writes data from this context back to the requesting process/thread. 128 /// Writes data from this context back to the requesting process/thread.
@@ -267,7 +268,7 @@ public:
267private: 268private:
268 friend class IPC::ResponseBuilder; 269 friend class IPC::ResponseBuilder;
269 270
270 void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); 271 void ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, bool incoming);
271 272
272 std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; 273 std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
273 Kernel::KServerSession* server_session{}; 274 Kernel::KServerSession* server_session{};
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
index 5a180b7dc..32aaf9fc5 100644
--- a/src/core/hle/kernel/k_auto_object.h
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -17,8 +17,6 @@ namespace Kernel {
17class KernelCore; 17class KernelCore;
18class KProcess; 18class KProcess;
19 19
20using Handle = u32;
21
22#define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \ 20#define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \
23 NON_COPYABLE(CLASS); \ 21 NON_COPYABLE(CLASS); \
24 NON_MOVEABLE(CLASS); \ 22 NON_MOVEABLE(CLASS); \
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index a9738f7ce..f51cf3e7b 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -179,7 +179,7 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) {
179 179
180 KThread* thread_to_close = nullptr; 180 KThread* thread_to_close = nullptr;
181 if (can_access) { 181 if (can_access) {
182 if (prev_tag == InvalidHandle) { 182 if (prev_tag == Svc::InvalidHandle) {
183 // If nobody held the lock previously, we're all good. 183 // If nobody held the lock previously, we're all good.
184 thread->SetSyncedObject(nullptr, RESULT_SUCCESS); 184 thread->SetSyncedObject(nullptr, RESULT_SUCCESS);
185 thread->Wakeup(); 185 thread->Wakeup();
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp
new file mode 100644
index 000000000..0378447f6
--- /dev/null
+++ b/src/core/hle/kernel/k_handle_table.cpp
@@ -0,0 +1,135 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_handle_table.h"
6
7namespace Kernel {
8
9KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
10KHandleTable ::~KHandleTable() = default;
11
12ResultCode KHandleTable::Finalize() {
13 // Get the table and clear our record of it.
14 u16 saved_table_size = 0;
15 {
16 KScopedSpinLock lk(m_lock);
17
18 std::swap(m_table_size, saved_table_size);
19 }
20
21 // Close and free all entries.
22 for (size_t i = 0; i < saved_table_size; i++) {
23 if (KAutoObject* obj = m_objects[i]; obj != nullptr) {
24 obj->Close();
25 }
26 }
27
28 return RESULT_SUCCESS;
29}
30
31bool KHandleTable::Remove(Handle handle) {
32 // Don't allow removal of a pseudo-handle.
33 if (Svc::IsPseudoHandle(handle)) {
34 return false;
35 }
36
37 // Handles must not have reserved bits set.
38 const auto handle_pack = HandlePack(handle);
39 if (handle_pack.reserved != 0) {
40 return false;
41 }
42
43 // Find the object and free the entry.
44 KAutoObject* obj = nullptr;
45 {
46 KScopedSpinLock lk(m_lock);
47
48 if (this->IsValidHandle(handle)) {
49 const auto index = handle_pack.index;
50
51 obj = m_objects[index];
52 this->FreeEntry(index);
53 } else {
54 return false;
55 }
56 }
57
58 // Close the object.
59 obj->Close();
60 return true;
61}
62
63ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
64 KScopedSpinLock lk(m_lock);
65
66 // Never exceed our capacity.
67 R_UNLESS(m_count < m_table_size, ResultOutOfHandles);
68
69 // Allocate entry, set output handle.
70 {
71 const auto linear_id = this->AllocateLinearId();
72 const auto index = this->AllocateEntry();
73
74 m_entry_infos[index].info = {.linear_id = linear_id, .type = type};
75 m_objects[index] = obj;
76
77 obj->Open();
78
79 *out_handle = EncodeHandle(static_cast<u16>(index), linear_id);
80 }
81
82 return RESULT_SUCCESS;
83}
84
85ResultCode KHandleTable::Reserve(Handle* out_handle) {
86 KScopedSpinLock lk(m_lock);
87
88 // Never exceed our capacity.
89 R_UNLESS(m_count < m_table_size, ResultOutOfHandles);
90
91 *out_handle = EncodeHandle(static_cast<u16>(this->AllocateEntry()), this->AllocateLinearId());
92 return RESULT_SUCCESS;
93}
94
95void KHandleTable::Unreserve(Handle handle) {
96 KScopedSpinLock lk(m_lock);
97
98 // Unpack the handle.
99 const auto handle_pack = HandlePack(handle);
100 const auto index = handle_pack.index;
101 const auto linear_id = handle_pack.linear_id;
102 const auto reserved = handle_pack.reserved;
103 ASSERT(reserved == 0);
104 ASSERT(linear_id != 0);
105
106 if (index < m_table_size) {
107 // NOTE: This code does not check the linear id.
108 ASSERT(m_objects[index] == nullptr);
109 this->FreeEntry(index);
110 }
111}
112
113void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) {
114 KScopedSpinLock lk(m_lock);
115
116 // Unpack the handle.
117 const auto handle_pack = HandlePack(handle);
118 const auto index = handle_pack.index;
119 const auto linear_id = handle_pack.linear_id;
120 const auto reserved = handle_pack.reserved;
121 ASSERT(reserved == 0);
122 ASSERT(linear_id != 0);
123
124 if (index < m_table_size) {
125 // Set the entry.
126 ASSERT(m_objects[index] == nullptr);
127
128 m_entry_infos[index].info = {.linear_id = static_cast<u16>(linear_id), .type = type};
129 m_objects[index] = obj;
130
131 obj->Open();
132 }
133}
134
135} // namespace Kernel
diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h
new file mode 100644
index 000000000..e38ad0fd9
--- /dev/null
+++ b/src/core/hle/kernel/k_handle_table.h
@@ -0,0 +1,309 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/assert.h"
10#include "common/bit_field.h"
11#include "common/bit_util.h"
12#include "common/common_types.h"
13#include "core/hle/kernel/k_auto_object.h"
14#include "core/hle/kernel/k_spin_lock.h"
15#include "core/hle/kernel/k_thread.h"
16#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/svc_common.h"
18#include "core/hle/kernel/svc_results.h"
19#include "core/hle/result.h"
20
21namespace Kernel {
22
23class KernelCore;
24
25class KHandleTable {
26 NON_COPYABLE(KHandleTable);
27 NON_MOVEABLE(KHandleTable);
28
29public:
30 static constexpr size_t MaxTableSize = 1024;
31
32private:
33 union HandlePack {
34 u32 raw;
35 BitField<0, 15, u32> index;
36 BitField<15, 15, u32> linear_id;
37 BitField<30, 2, u32> reserved;
38 };
39
40 static constexpr u16 MinLinearId = 1;
41 static constexpr u16 MaxLinearId = 0x7FFF;
42
43 static constexpr Handle EncodeHandle(u16 index, u16 linear_id) {
44 HandlePack handle{};
45 handle.index.Assign(index);
46 handle.linear_id.Assign(linear_id);
47 handle.reserved.Assign(0);
48 return handle.raw;
49 }
50
51 union EntryInfo {
52 struct {
53 u16 linear_id;
54 u16 type;
55 } info;
56 s32 next_free_index;
57
58 constexpr u16 GetLinearId() const {
59 return info.linear_id;
60 }
61 constexpr u16 GetType() const {
62 return info.type;
63 }
64 constexpr s32 GetNextFreeIndex() const {
65 return next_free_index;
66 }
67 };
68
69private:
70 std::array<EntryInfo, MaxTableSize> m_entry_infos{};
71 std::array<KAutoObject*, MaxTableSize> m_objects{};
72 s32 m_free_head_index{-1};
73 u16 m_table_size{};
74 u16 m_max_count{};
75 u16 m_next_linear_id{MinLinearId};
76 u16 m_count{};
77 mutable KSpinLock m_lock;
78
79public:
80 explicit KHandleTable(KernelCore& kernel_);
81 ~KHandleTable();
82
83 constexpr ResultCode Initialize(s32 size) {
84 R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
85
86 // Initialize all fields.
87 m_max_count = 0;
88 m_table_size = static_cast<u16>((size <= 0) ? MaxTableSize : size);
89 m_next_linear_id = MinLinearId;
90 m_count = 0;
91 m_free_head_index = -1;
92
93 // Free all entries.
94 for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
95 m_objects[i] = nullptr;
96 m_entry_infos[i].next_free_index = i - 1;
97 m_free_head_index = i;
98 }
99
100 return RESULT_SUCCESS;
101 }
102
103 constexpr size_t GetTableSize() const {
104 return m_table_size;
105 }
106 constexpr size_t GetCount() const {
107 return m_count;
108 }
109 constexpr size_t GetMaxCount() const {
110 return m_max_count;
111 }
112
113 ResultCode Finalize();
114 bool Remove(Handle handle);
115
116 template <typename T = KAutoObject>
117 KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const {
118 // Lock and look up in table.
119 KScopedSpinLock lk(m_lock);
120
121 if constexpr (std::is_same<T, KAutoObject>::value) {
122 return this->GetObjectImpl(handle);
123 } else {
124 if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) {
125 return obj->DynamicCast<T*>();
126 } else {
127 return nullptr;
128 }
129 }
130 }
131
132 template <typename T = KAutoObject>
133 KScopedAutoObject<T> GetObject(Handle handle) const {
134 // Handle pseudo-handles.
135 if constexpr (std::derived_from<KProcess, T>) {
136 if (handle == Svc::PseudoHandle::CurrentProcess) {
137 auto* const cur_process = kernel.CurrentProcess();
138 ASSERT(cur_process != nullptr);
139 return cur_process;
140 }
141 } else if constexpr (std::derived_from<KThread, T>) {
142 if (handle == Svc::PseudoHandle::CurrentThread) {
143 auto* const cur_thread = GetCurrentThreadPointer(kernel);
144 ASSERT(cur_thread != nullptr);
145 return cur_thread;
146 }
147 }
148
149 return this->template GetObjectWithoutPseudoHandle<T>(handle);
150 }
151
152 ResultCode Reserve(Handle* out_handle);
153 void Unreserve(Handle handle);
154
155 template <typename T>
156 ResultCode Add(Handle* out_handle, T* obj) {
157 static_assert(std::is_base_of<KAutoObject, T>::value);
158 return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken());
159 }
160
161 template <typename T>
162 void Register(Handle handle, T* obj) {
163 static_assert(std::is_base_of<KAutoObject, T>::value);
164 return this->Register(handle, obj, obj->GetTypeObj().GetClassToken());
165 }
166
167 template <typename T>
168 bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const {
169 // Try to convert and open all the handles.
170 size_t num_opened;
171 {
172 // Lock the table.
173 KScopedSpinLock lk(m_lock);
174 for (num_opened = 0; num_opened < num_handles; num_opened++) {
175 // Get the current handle.
176 const auto cur_handle = handles[num_opened];
177
178 // Get the object for the current handle.
179 KAutoObject* cur_object = this->GetObjectImpl(cur_handle);
180 if (cur_object == nullptr) {
181 break;
182 }
183
184 // Cast the current object to the desired type.
185 T* cur_t = cur_object->DynamicCast<T*>();
186 if (cur_t == nullptr) {
187 break;
188 }
189
190 // Open a reference to the current object.
191 cur_t->Open();
192 out[num_opened] = cur_t;
193 }
194 }
195
196 // If we converted every object, succeed.
197 if (num_opened == num_handles) {
198 return true;
199 }
200
201 // If we didn't convert entry object, close the ones we opened.
202 for (size_t i = 0; i < num_opened; i++) {
203 out[i]->Close();
204 }
205
206 return false;
207 }
208
209private:
210 ResultCode Add(Handle* out_handle, KAutoObject* obj, u16 type);
211 void Register(Handle handle, KAutoObject* obj, u16 type);
212
213 constexpr s32 AllocateEntry() {
214 ASSERT(m_count < m_table_size);
215
216 const auto index = m_free_head_index;
217
218 m_free_head_index = m_entry_infos[index].GetNextFreeIndex();
219
220 m_max_count = std::max(m_max_count, ++m_count);
221
222 return index;
223 }
224
225 constexpr void FreeEntry(s32 index) {
226 ASSERT(m_count > 0);
227
228 m_objects[index] = nullptr;
229 m_entry_infos[index].next_free_index = m_free_head_index;
230
231 m_free_head_index = index;
232
233 --m_count;
234 }
235
236 constexpr u16 AllocateLinearId() {
237 const u16 id = m_next_linear_id++;
238 if (m_next_linear_id > MaxLinearId) {
239 m_next_linear_id = MinLinearId;
240 }
241 return id;
242 }
243
244 constexpr bool IsValidHandle(Handle handle) const {
245 // Unpack the handle.
246 const auto handle_pack = HandlePack(handle);
247 const auto raw_value = handle_pack.raw;
248 const auto index = handle_pack.index;
249 const auto linear_id = handle_pack.linear_id;
250 const auto reserved = handle_pack.reserved;
251 ASSERT(reserved == 0);
252
253 // Validate our indexing information.
254 if (raw_value == 0) {
255 return false;
256 }
257 if (linear_id == 0) {
258 return false;
259 }
260 if (index >= m_table_size) {
261 return false;
262 }
263
264 // Check that there's an object, and our serial id is correct.
265 if (m_objects[index] == nullptr) {
266 return false;
267 }
268 if (m_entry_infos[index].GetLinearId() != linear_id) {
269 return false;
270 }
271
272 return true;
273 }
274
275 constexpr KAutoObject* GetObjectImpl(Handle handle) const {
276 // Handles must not have reserved bits set.
277 const auto handle_pack = HandlePack(handle);
278 if (handle_pack.reserved != 0) {
279 return nullptr;
280 }
281
282 if (this->IsValidHandle(handle)) {
283 return m_objects[handle_pack.index];
284 } else {
285 return nullptr;
286 }
287 }
288
289 constexpr KAutoObject* GetObjectByIndexImpl(Handle* out_handle, size_t index) const {
290
291 // Index must be in bounds.
292 if (index >= m_table_size) {
293 return nullptr;
294 }
295
296 // Ensure entry has an object.
297 if (KAutoObject* obj = m_objects[index]; obj != nullptr) {
298 *out_handle = EncodeHandle(static_cast<u16>(index), m_entry_infos[index].GetLinearId());
299 return obj;
300 } else {
301 return nullptr;
302 }
303 }
304
305private:
306 KernelCore& kernel;
307};
308
309} // namespace Kernel
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index e542b1f07..174318180 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -354,7 +354,7 @@ ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
354 tls_region_address = CreateTLSRegion(); 354 tls_region_address = CreateTLSRegion();
355 memory_reservation.Commit(); 355 memory_reservation.Commit();
356 356
357 return handle_table.SetSize(capabilities.GetHandleTableSize()); 357 return handle_table.Initialize(capabilities.GetHandleTableSize());
358} 358}
359 359
360void KProcess::Run(s32 main_thread_priority, u64 stack_size) { 360void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 5c54c6360..62ab26b05 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -11,10 +11,10 @@
11#include <unordered_map> 11#include <unordered_map>
12#include <vector> 12#include <vector>
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "core/hle/kernel/handle_table.h"
15#include "core/hle/kernel/k_address_arbiter.h" 14#include "core/hle/kernel/k_address_arbiter.h"
16#include "core/hle/kernel/k_auto_object.h" 15#include "core/hle/kernel/k_auto_object.h"
17#include "core/hle/kernel/k_condition_variable.h" 16#include "core/hle/kernel/k_condition_variable.h"
17#include "core/hle/kernel/k_handle_table.h"
18#include "core/hle/kernel/k_synchronization_object.h" 18#include "core/hle/kernel/k_synchronization_object.h"
19#include "core/hle/kernel/process_capability.h" 19#include "core/hle/kernel/process_capability.h"
20#include "core/hle/kernel/slab_helpers.h" 20#include "core/hle/kernel/slab_helpers.h"
@@ -104,12 +104,12 @@ public:
104 } 104 }
105 105
106 /// Gets a reference to the process' handle table. 106 /// Gets a reference to the process' handle table.
107 HandleTable& GetHandleTable() { 107 KHandleTable& GetHandleTable() {
108 return handle_table; 108 return handle_table;
109 } 109 }
110 110
111 /// Gets a const reference to the process' handle table. 111 /// Gets a const reference to the process' handle table.
112 const HandleTable& GetHandleTable() const { 112 const KHandleTable& GetHandleTable() const {
113 return handle_table; 113 return handle_table;
114 } 114 }
115 115
@@ -429,7 +429,7 @@ private:
429 u64 total_process_running_time_ticks = 0; 429 u64 total_process_running_time_ticks = 0;
430 430
431 /// Per-process handle table for storing created object handles in. 431 /// Per-process handle table for storing created object handles in.
432 HandleTable handle_table; 432 KHandleTable handle_table;
433 433
434 /// Per-process address arbiter. 434 /// Per-process address arbiter.
435 KAddressArbiter address_arbiter; 435 KAddressArbiter address_arbiter;
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
index ebecf0c77..1bfbbcfe2 100644
--- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
+++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
@@ -8,7 +8,7 @@
8#pragma once 8#pragma once
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/kernel/handle_table.h" 11#include "core/hle/kernel/k_handle_table.h"
12#include "core/hle/kernel/k_thread.h" 12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/time_manager.h" 14#include "core/hle/kernel/time_manager.h"
@@ -17,7 +17,7 @@ namespace Kernel {
17 17
18class [[nodiscard]] KScopedSchedulerLockAndSleep { 18class [[nodiscard]] KScopedSchedulerLockAndSleep {
19public: 19public:
20 explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout) 20 explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, KThread* t, s64 timeout)
21 : kernel(kernel), thread(t), timeout_tick(timeout) { 21 : kernel(kernel), thread(t), timeout_tick(timeout) {
22 // Lock the scheduler. 22 // Lock the scheduler.
23 kernel.GlobalSchedulerContext().scheduler_lock.Lock(); 23 kernel.GlobalSchedulerContext().scheduler_lock.Lock();
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 3bc259693..c8acaa453 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -10,9 +10,9 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "core/core_timing.h" 11#include "core/core_timing.h"
12#include "core/hle/ipc_helpers.h" 12#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/handle_table.h"
14#include "core/hle/kernel/hle_ipc.h" 13#include "core/hle/kernel/hle_ipc.h"
15#include "core/hle/kernel/k_client_port.h" 14#include "core/hle/kernel/k_client_port.h"
15#include "core/hle/kernel/k_handle_table.h"
16#include "core/hle/kernel/k_process.h" 16#include "core/hle/kernel/k_process.h"
17#include "core/hle/kernel/k_scheduler.h" 17#include "core/hle/kernel/k_scheduler.h"
18#include "core/hle/kernel/k_server_session.h" 18#include "core/hle/kernel/k_server_session.h"
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 3de0157ac..ef6dfeeca 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -18,8 +18,8 @@
18#include "core/core.h" 18#include "core/core.h"
19#include "core/cpu_manager.h" 19#include "core/cpu_manager.h"
20#include "core/hardware_properties.h" 20#include "core/hardware_properties.h"
21#include "core/hle/kernel/handle_table.h"
22#include "core/hle/kernel/k_condition_variable.h" 21#include "core/hle/kernel/k_condition_variable.h"
22#include "core/hle/kernel/k_handle_table.h"
23#include "core/hle/kernel/k_memory_layout.h" 23#include "core/hle/kernel/k_memory_layout.h"
24#include "core/hle/kernel/k_process.h" 24#include "core/hle/kernel/k_process.h"
25#include "core/hle/kernel/k_resource_limit.h" 25#include "core/hle/kernel/k_resource_limit.h"
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f64e07081..825fab694 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -26,9 +26,9 @@
26#include "core/cpu_manager.h" 26#include "core/cpu_manager.h"
27#include "core/device_memory.h" 27#include "core/device_memory.h"
28#include "core/hardware_properties.h" 28#include "core/hardware_properties.h"
29#include "core/hle/kernel/handle_table.h"
30#include "core/hle/kernel/init/init_slab_setup.h" 29#include "core/hle/kernel/init/init_slab_setup.h"
31#include "core/hle/kernel/k_client_port.h" 30#include "core/hle/kernel/k_client_port.h"
31#include "core/hle/kernel/k_handle_table.h"
32#include "core/hle/kernel/k_memory_layout.h" 32#include "core/hle/kernel/k_memory_layout.h"
33#include "core/hle/kernel/k_memory_manager.h" 33#include "core/hle/kernel/k_memory_manager.h"
34#include "core/hle/kernel/k_process.h" 34#include "core/hle/kernel/k_process.h"
@@ -52,8 +52,7 @@ namespace Kernel {
52 52
53struct KernelCore::Impl { 53struct KernelCore::Impl {
54 explicit Impl(Core::System& system, KernelCore& kernel) 54 explicit Impl(Core::System& system, KernelCore& kernel)
55 : time_manager{system}, global_handle_table{kernel}, 55 : time_manager{system}, object_list_container{kernel}, system{system} {}
56 object_list_container{kernel}, system{system} {}
57 56
58 void SetMulticore(bool is_multicore) { 57 void SetMulticore(bool is_multicore) {
59 this->is_multicore = is_multicore; 58 this->is_multicore = is_multicore;
@@ -61,6 +60,7 @@ struct KernelCore::Impl {
61 60
62 void Initialize(KernelCore& kernel) { 61 void Initialize(KernelCore& kernel) {
63 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); 62 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
63 global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
64 64
65 service_thread_manager = 65 service_thread_manager =
66 std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); 66 std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
@@ -118,7 +118,7 @@ struct KernelCore::Impl {
118 current_process = nullptr; 118 current_process = nullptr;
119 } 119 }
120 120
121 global_handle_table.Clear(); 121 global_handle_table.reset();
122 122
123 preemption_event = nullptr; 123 preemption_event = nullptr;
124 124
@@ -648,7 +648,7 @@ struct KernelCore::Impl {
648 648
649 // This is the kernel's handle table or supervisor handle table which 649 // This is the kernel's handle table or supervisor handle table which
650 // stores all the objects in place. 650 // stores all the objects in place.
651 HandleTable global_handle_table; 651 std::unique_ptr<KHandleTable> global_handle_table;
652 652
653 KAutoObjectWithListContainer object_list_container; 653 KAutoObjectWithListContainer object_list_container;
654 654
@@ -722,7 +722,7 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
722} 722}
723 723
724KScopedAutoObject<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { 724KScopedAutoObject<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
725 return impl->global_handle_table.GetObject<KThread>(handle); 725 return impl->global_handle_table->GetObject<KThread>(handle);
726} 726}
727 727
728void KernelCore::AppendNewProcess(KProcess* process) { 728void KernelCore::AppendNewProcess(KProcess* process) {
@@ -876,12 +876,12 @@ u64 KernelCore::CreateNewUserProcessID() {
876 return impl->next_user_process_id++; 876 return impl->next_user_process_id++;
877} 877}
878 878
879Kernel::HandleTable& KernelCore::GlobalHandleTable() { 879KHandleTable& KernelCore::GlobalHandleTable() {
880 return impl->global_handle_table; 880 return *impl->global_handle_table;
881} 881}
882 882
883const Kernel::HandleTable& KernelCore::GlobalHandleTable() const { 883const KHandleTable& KernelCore::GlobalHandleTable() const {
884 return impl->global_handle_table; 884 return *impl->global_handle_table;
885} 885}
886 886
887void KernelCore::RegisterCoreThread(std::size_t core_id) { 887void KernelCore::RegisterCoreThread(std::size_t core_id) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 0dd9deaeb..7c46aa997 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -14,6 +14,7 @@
14#include "core/hle/kernel/k_auto_object.h" 14#include "core/hle/kernel/k_auto_object.h"
15#include "core/hle/kernel/k_slab_heap.h" 15#include "core/hle/kernel/k_slab_heap.h"
16#include "core/hle/kernel/memory_types.h" 16#include "core/hle/kernel/memory_types.h"
17#include "core/hle/kernel/svc_common.h"
17 18
18namespace Core { 19namespace Core {
19class CPUInterruptHandler; 20class CPUInterruptHandler;
@@ -30,10 +31,10 @@ namespace Kernel {
30 31
31class KClientPort; 32class KClientPort;
32class GlobalSchedulerContext; 33class GlobalSchedulerContext;
33class HandleTable;
34class KAutoObjectWithListContainer; 34class KAutoObjectWithListContainer;
35class KClientSession; 35class KClientSession;
36class KEvent; 36class KEvent;
37class KHandleTable;
37class KLinkedListNode; 38class KLinkedListNode;
38class KMemoryManager; 39class KMemoryManager;
39class KPort; 40class KPort;
@@ -308,10 +309,10 @@ private:
308 u64 CreateNewThreadID(); 309 u64 CreateNewThreadID();
309 310
310 /// Provides a reference to the global handle table. 311 /// Provides a reference to the global handle table.
311 Kernel::HandleTable& GlobalHandleTable(); 312 KHandleTable& GlobalHandleTable();
312 313
313 /// Provides a const reference to the global handle table. 314 /// Provides a const reference to the global handle table.
314 const Kernel::HandleTable& GlobalHandleTable() const; 315 const KHandleTable& GlobalHandleTable() const;
315 316
316 struct Impl; 317 struct Impl;
317 std::unique_ptr<Impl> impl; 318 std::unique_ptr<Impl> impl;
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp
index 4ccac0b06..fcb8b1ea5 100644
--- a/src/core/hle/kernel/process_capability.cpp
+++ b/src/core/hle/kernel/process_capability.cpp
@@ -6,7 +6,7 @@
6 6
7#include "common/bit_util.h" 7#include "common/bit_util.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/hle/kernel/handle_table.h" 9#include "core/hle/kernel/k_handle_table.h"
10#include "core/hle/kernel/k_page_table.h" 10#include "core/hle/kernel/k_page_table.h"
11#include "core/hle/kernel/process_capability.h" 11#include "core/hle/kernel/process_capability.h"
12#include "core/hle/kernel/svc_results.h" 12#include "core/hle/kernel/svc_results.h"
@@ -99,7 +99,7 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() {
99 interrupt_capabilities.set(); 99 interrupt_capabilities.set();
100 100
101 // Allow using the maximum possible amount of handles 101 // Allow using the maximum possible amount of handles
102 handle_table_size = static_cast<s32>(HandleTable::MAX_COUNT); 102 handle_table_size = static_cast<s32>(KHandleTable::MaxTableSize);
103 103
104 // Allow all debugging capabilities. 104 // Allow all debugging capabilities.
105 is_debuggable = true; 105 is_debuggable = true;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 156c565b0..d3293a1fe 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -21,12 +21,12 @@
21#include "core/core_timing.h" 21#include "core/core_timing.h"
22#include "core/core_timing_util.h" 22#include "core/core_timing_util.h"
23#include "core/cpu_manager.h" 23#include "core/cpu_manager.h"
24#include "core/hle/kernel/handle_table.h"
25#include "core/hle/kernel/k_address_arbiter.h" 24#include "core/hle/kernel/k_address_arbiter.h"
26#include "core/hle/kernel/k_client_port.h" 25#include "core/hle/kernel/k_client_port.h"
27#include "core/hle/kernel/k_client_session.h" 26#include "core/hle/kernel/k_client_session.h"
28#include "core/hle/kernel/k_condition_variable.h" 27#include "core/hle/kernel/k_condition_variable.h"
29#include "core/hle/kernel/k_event.h" 28#include "core/hle/kernel/k_event.h"
29#include "core/hle/kernel/k_handle_table.h"
30#include "core/hle/kernel/k_memory_block.h" 30#include "core/hle/kernel/k_memory_block.h"
31#include "core/hle/kernel/k_memory_layout.h" 31#include "core/hle/kernel/k_memory_layout.h"
32#include "core/hle/kernel/k_page_table.h" 32#include "core/hle/kernel/k_page_table.h"
@@ -839,10 +839,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
839 } 839 }
840 840
841 KProcess* const current_process = system.Kernel().CurrentProcess(); 841 KProcess* const current_process = system.Kernel().CurrentProcess();
842 HandleTable& handle_table = current_process->GetHandleTable(); 842 KHandleTable& handle_table = current_process->GetHandleTable();
843 const auto resource_limit = current_process->GetResourceLimit(); 843 const auto resource_limit = current_process->GetResourceLimit();
844 if (!resource_limit) { 844 if (!resource_limit) {
845 *result = KernelHandle::InvalidHandle; 845 *result = Svc::InvalidHandle;
846 // Yes, the kernel considers this a successful operation. 846 // Yes, the kernel considers this a successful operation.
847 return RESULT_SUCCESS; 847 return RESULT_SUCCESS;
848 } 848 }
@@ -1993,7 +1993,7 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
1993 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); 1993 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1994 1994
1995 // Get the current handle table. 1995 // Get the current handle table.
1996 const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1996 const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1997 1997
1998 // Get the writable event. 1998 // Get the writable event.
1999 KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle); 1999 KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle);
diff --git a/src/core/hle/kernel/svc_common.h b/src/core/hle/kernel/svc_common.h
index 4af049551..8a8f347b5 100644
--- a/src/core/hle/kernel/svc_common.h
+++ b/src/core/hle/kernel/svc_common.h
@@ -6,9 +6,24 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9namespace Kernel {
10using Handle = u32;
11}
12
9namespace Kernel::Svc { 13namespace Kernel::Svc {
10 14
11constexpr s32 ArgumentHandleCountMax = 0x40; 15constexpr s32 ArgumentHandleCountMax = 0x40;
12constexpr u32 HandleWaitMask{1u << 30}; 16constexpr u32 HandleWaitMask{1u << 30};
13 17
18constexpr inline Handle InvalidHandle = Handle(0);
19
20enum PseudoHandle : Handle {
21 CurrentThread = 0xFFFF8000,
22 CurrentProcess = 0xFFFF8001,
23};
24
25constexpr bool IsPseudoHandle(const Handle& handle) {
26 return handle == PseudoHandle::CurrentProcess || handle == PseudoHandle::CurrentThread;
27}
28
14} // namespace Kernel::Svc 29} // namespace Kernel::Svc
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 59ebfc51f..ae9b4be2f 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -6,7 +6,6 @@
6#include "core/core.h" 6#include "core/core.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/core_timing_util.h" 8#include "core/core_timing_util.h"
9#include "core/hle/kernel/handle_table.h"
10#include "core/hle/kernel/k_scheduler.h" 9#include "core/hle/kernel/k_scheduler.h"
11#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
12#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index f040b4c08..bdfda6c54 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -12,8 +12,8 @@
12#include "common/assert.h" 12#include "common/assert.h"
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/kernel/handle_table.h"
16#include "core/hle/kernel/k_class_token.h" 15#include "core/hle/kernel/k_class_token.h"
16#include "core/hle/kernel/k_handle_table.h"
17#include "core/hle/kernel/k_process.h" 17#include "core/hle/kernel/k_process.h"
18#include "core/hle/kernel/k_readable_event.h" 18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/kernel/k_scheduler.h" 19#include "core/hle/kernel/k_scheduler.h"
@@ -115,7 +115,7 @@ QString WaitTreeText::GetText() const {
115 return text; 115 return text;
116} 116}
117 117
118WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table) 118WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table)
119 : mutex_address(mutex_address) { 119 : mutex_address(mutex_address) {
120 mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); 120 mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address);
121 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); 121 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask);
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 3dd4acab0..d450345df 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -14,11 +14,12 @@
14 14
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "core/hle/kernel/k_auto_object.h" 16#include "core/hle/kernel/k_auto_object.h"
17#include "core/hle/kernel/svc_common.h"
17 18
18class EmuThread; 19class EmuThread;
19 20
20namespace Kernel { 21namespace Kernel {
21class HandleTable; 22class KHandleTable;
22class KReadableEvent; 23class KReadableEvent;
23class KSynchronizationObject; 24class KSynchronizationObject;
24class KThread; 25class KThread;
@@ -74,7 +75,7 @@ public:
74class WaitTreeMutexInfo : public WaitTreeExpandableItem { 75class WaitTreeMutexInfo : public WaitTreeExpandableItem {
75 Q_OBJECT 76 Q_OBJECT
76public: 77public:
77 explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table); 78 explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table);
78 ~WaitTreeMutexInfo() override; 79 ~WaitTreeMutexInfo() override;
79 80
80 QString GetText() const override; 81 QString GetText() const override;