summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/handle_table.cpp77
-rw-r--r--src/core/hle/kernel/handle_table.h32
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp8
-rw-r--r--src/core/hle/kernel/hle_ipc.h10
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
-rw-r--r--src/yuzu/debugger/wait_tree.h8
7 files changed, 28 insertions, 111 deletions
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 9291f0a76..cd752da4e 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -47,50 +47,6 @@ ResultCode HandleTable::SetSize(s32 handle_table_size) {
47 return RESULT_SUCCESS; 47 return RESULT_SUCCESS;
48} 48}
49 49
50ResultVal<Handle> HandleTable::Create(Object* obj) {
51 DEBUG_ASSERT(obj != nullptr);
52
53 switch (obj->GetHandleType()) {
54 case HandleType::SharedMemory:
55 case HandleType::Thread:
56 case HandleType::Event:
57 case HandleType::Process:
58 case HandleType::ReadableEvent:
59 case HandleType::WritableEvent:
60 case HandleType::ClientSession:
61 case HandleType::ServerSession:
62 case HandleType::Session:
63 case HandleType::TransferMemory: {
64 Handle handle{};
65 Add(&handle, reinterpret_cast<KAutoObject*>(obj), {});
66 return MakeResult<Handle>(handle);
67 }
68 default:
69 break;
70 }
71
72 const u16 slot = next_free_slot;
73 if (slot >= table_size) {
74 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
75 return ResultOutOfHandles;
76 }
77 next_free_slot = generations[slot];
78
79 const u16 generation = next_generation++;
80
81 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
82 // Horizon OS uses zero to represent an invalid handle, so skip to 1.
83 if (next_generation >= (1 << 15)) {
84 next_generation = 1;
85 }
86
87 generations[slot] = generation;
88 objects[slot] = std::move(SharedFrom(obj));
89
90 Handle handle = generation | (slot << 15);
91 return MakeResult<Handle>(handle);
92}
93
94ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { 50ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
95 ASSERT(obj != nullptr); 51 ASSERT(obj != nullptr);
96 52
@@ -110,7 +66,7 @@ ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
110 } 66 }
111 67
112 generations[slot] = generation; 68 generations[slot] = generation;
113 objects_new[slot] = obj; 69 objects[slot] = obj;
114 obj->Open(); 70 obj->Open();
115 71
116 *out_handle = generation | (slot << 15); 72 *out_handle = generation | (slot << 15);
@@ -119,12 +75,16 @@ ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
119} 75}
120 76
121ResultVal<Handle> HandleTable::Duplicate(Handle handle) { 77ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
122 auto object = GetGeneric(handle); 78 auto object = GetObject(handle);
123 if (object == nullptr) { 79 if (object.IsNull()) {
124 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle); 80 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
125 return ResultInvalidHandle; 81 return ResultInvalidHandle;
126 } 82 }
127 return Create(object); 83
84 Handle out_handle{};
85 R_TRY(Add(&out_handle, object.GetPointerUnsafe()));
86
87 return MakeResult(out_handle);
128} 88}
129 89
130bool HandleTable::Remove(Handle handle) { 90bool HandleTable::Remove(Handle handle) {
@@ -139,12 +99,7 @@ bool HandleTable::Remove(Handle handle) {
139 objects[slot]->Close(); 99 objects[slot]->Close();
140 } 100 }
141 101
142 if (objects_new[slot]) {
143 objects_new[slot]->Close();
144 }
145
146 objects[slot] = nullptr; 102 objects[slot] = nullptr;
147 objects_new[slot] = nullptr;
148 103
149 generations[slot] = next_free_slot; 104 generations[slot] = next_free_slot;
150 next_free_slot = slot; 105 next_free_slot = slot;
@@ -155,28 +110,14 @@ bool HandleTable::Remove(Handle handle) {
155bool HandleTable::IsValid(Handle handle) const { 110bool HandleTable::IsValid(Handle handle) const {
156 const std::size_t slot = GetSlot(handle); 111 const std::size_t slot = GetSlot(handle);
157 const u16 generation = GetGeneration(handle); 112 const u16 generation = GetGeneration(handle);
158 const bool is_object_valid = (objects[slot] != nullptr) || (objects_new[slot] != nullptr); 113 const bool is_object_valid = (objects[slot] != nullptr);
159 return slot < table_size && is_object_valid && generations[slot] == generation; 114 return slot < table_size && is_object_valid && generations[slot] == generation;
160} 115}
161 116
162Object* HandleTable::GetGeneric(Handle handle) const {
163 if (handle == CurrentThread) {
164 return (kernel.CurrentScheduler()->GetCurrentThread());
165 } else if (handle == CurrentProcess) {
166 return (kernel.CurrentProcess());
167 }
168
169 if (!IsValid(handle)) {
170 return nullptr;
171 }
172 return objects[GetSlot(handle)].get();
173}
174
175void HandleTable::Clear() { 117void HandleTable::Clear() {
176 for (u16 i = 0; i < table_size; ++i) { 118 for (u16 i = 0; i < table_size; ++i) {
177 generations[i] = static_cast<u16>(i + 1); 119 generations[i] = static_cast<u16>(i + 1);
178 objects[i] = nullptr; 120 objects[i] = nullptr;
179 objects_new[i] = nullptr;
180 } 121 }
181 next_free_slot = 0; 122 next_free_slot = 0;
182} 123}
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index d6abdcd47..2e0b2d8b8 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -71,13 +71,6 @@ public:
71 ResultCode SetSize(s32 handle_table_size); 71 ResultCode SetSize(s32 handle_table_size);
72 72
73 /** 73 /**
74 * Allocates a handle for the given object.
75 * @return The created Handle or one of the following errors:
76 * - `ERR_HANDLE_TABLE_FULL`: the maximum number of handles has been exceeded.
77 */
78 ResultVal<Handle> Create(Object* obj);
79
80 /**
81 * Returns a new handle that points to the same object as the passed in handle. 74 * Returns a new handle that points to the same object as the passed in handle.
82 * @return The duplicated Handle or one of the following errors: 75 * @return The duplicated Handle or one of the following errors:
83 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. 76 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
@@ -95,29 +88,13 @@ public:
95 /// Checks if a handle is valid and points to an existing object. 88 /// Checks if a handle is valid and points to an existing object.
96 bool IsValid(Handle handle) const; 89 bool IsValid(Handle handle) const;
97 90
98 /**
99 * Looks up a handle.
100 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
101 */
102 Object* GetGeneric(Handle handle) const;
103
104 /**
105 * Looks up a handle while verifying its type.
106 * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
107 * type differs from the requested one.
108 */
109 template <class T>
110 T* Get(Handle handle) const {
111 return DynamicObjectCast<T>(GetGeneric(handle));
112 }
113
114 template <typename T = KAutoObject> 91 template <typename T = KAutoObject>
115 KAutoObject* GetObjectImpl(Handle handle) const { 92 KAutoObject* GetObjectImpl(Handle handle) const {
116 if (!IsValid(handle)) { 93 if (!IsValid(handle)) {
117 return nullptr; 94 return nullptr;
118 } 95 }
119 96
120 auto* obj = objects_new[static_cast<u16>(handle >> 15)]; 97 auto* obj = objects[static_cast<u16>(handle >> 15)];
121 return obj->DynamicCast<T*>(); 98 return obj->DynamicCast<T*>();
122 } 99 }
123 100
@@ -133,7 +110,7 @@ public:
133 return nullptr; 110 return nullptr;
134 } 111 }
135 112
136 auto* obj = objects_new[static_cast<u16>(handle >> 15)]; 113 auto* obj = objects[static_cast<u16>(handle >> 15)];
137 return obj->DynamicCast<T*>(); 114 return obj->DynamicCast<T*>();
138 } 115 }
139 116
@@ -142,7 +119,7 @@ public:
142 if (!IsValid(handle)) { 119 if (!IsValid(handle)) {
143 return nullptr; 120 return nullptr;
144 } 121 }
145 auto* obj = objects_new[static_cast<u16>(handle >> 15)]; 122 auto* obj = objects[static_cast<u16>(handle >> 15)];
146 return obj->DynamicCast<T*>(); 123 return obj->DynamicCast<T*>();
147 } 124 }
148 125
@@ -203,8 +180,7 @@ public:
203 180
204private: 181private:
205 /// Stores the Object referenced by the handle or null if the slot is empty. 182 /// Stores the Object referenced by the handle or null if the slot is empty.
206 std::array<std::shared_ptr<Object>, MAX_COUNT> objects; 183 std::array<KAutoObject*, MAX_COUNT> objects{};
207 std::array<KAutoObject*, MAX_COUNT> objects_new{};
208 184
209 /** 185 /**
210 * The value of `next_generation` when the handle was created, used to check for validity. For 186 * The value of `next_generation` when the handle was created, used to check for validity. For
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index d647d9dd3..9e1e63204 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -74,12 +74,12 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
74 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { 74 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
75 const u32 copy_handle{rp.Pop<Handle>()}; 75 const u32 copy_handle{rp.Pop<Handle>()};
76 copy_handles.push_back(copy_handle); 76 copy_handles.push_back(copy_handle);
77 copy_objects.push_back(handle_table.GetGeneric(copy_handle)); 77 copy_objects.push_back(handle_table.GetObject(copy_handle).GetPointerUnsafe());
78 } 78 }
79 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { 79 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
80 const u32 move_handle{rp.Pop<Handle>()}; 80 const u32 move_handle{rp.Pop<Handle>()};
81 move_handles.push_back(move_handle); 81 move_handles.push_back(move_handle);
82 move_objects.push_back(handle_table.GetGeneric(move_handle)); 82 move_objects.push_back(handle_table.GetObject(move_handle).GetPointerUnsafe());
83 } 83 }
84 } else { 84 } else {
85 // For responses we just ignore the handles, they're empty and will be populated when 85 // For responses we just ignore the handles, they're empty and will be populated when
@@ -220,12 +220,12 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& thread) {
220 // for specific values in each of these descriptors. 220 // for specific values in each of these descriptors.
221 for (auto& object : copy_objects) { 221 for (auto& object : copy_objects) {
222 ASSERT(object != nullptr); 222 ASSERT(object != nullptr);
223 dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap(); 223 R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object));
224 } 224 }
225 225
226 for (auto& object : move_objects) { 226 for (auto& object : move_objects) {
227 ASSERT(object != nullptr); 227 ASSERT(object != nullptr);
228 dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap(); 228 R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object));
229 } 229 }
230 } 230 }
231 231
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index dc5c3b47d..b7484c445 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -16,7 +16,7 @@
16#include "common/concepts.h" 16#include "common/concepts.h"
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/object.h" 19#include "core/hle/kernel/k_auto_object.h"
20 20
21union ResultCode; 21union ResultCode;
22 22
@@ -228,11 +228,11 @@ public:
228 return DynamicObjectCast<T>(move_objects.at(index)); 228 return DynamicObjectCast<T>(move_objects.at(index));
229 } 229 }
230 230
231 void AddMoveObject(Object* object) { 231 void AddMoveObject(KAutoObject* object) {
232 move_objects.emplace_back(object); 232 move_objects.emplace_back(object);
233 } 233 }
234 234
235 void AddCopyObject(Object* object) { 235 void AddCopyObject(KAutoObject* object) {
236 copy_objects.emplace_back(object); 236 copy_objects.emplace_back(object);
237 } 237 }
238 238
@@ -292,8 +292,8 @@ private:
292 // TODO(yuriks): Check common usage of this and optimize size accordingly 292 // TODO(yuriks): Check common usage of this and optimize size accordingly
293 boost::container::small_vector<Handle, 8> move_handles; 293 boost::container::small_vector<Handle, 8> move_handles;
294 boost::container::small_vector<Handle, 8> copy_handles; 294 boost::container::small_vector<Handle, 8> copy_handles;
295 boost::container::small_vector<Object*, 8> move_objects; 295 boost::container::small_vector<KAutoObject*, 8> move_objects;
296 boost::container::small_vector<Object*, 8> copy_objects; 296 boost::container::small_vector<KAutoObject*, 8> copy_objects;
297 boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; 297 boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
298 298
299 std::optional<IPC::CommandHeader> command_header; 299 std::optional<IPC::CommandHeader> command_header;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index a78bfd1da..fa85bd631 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -328,7 +328,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
328 328
329 // Return the client session 329 // Return the client session
330 auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 330 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
331 CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); 331 handle_table.Add(out_handle, client_session);
332 return RESULT_SUCCESS; 332 return RESULT_SUCCESS;
333} 333}
334 334
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index f4eeba2c5..317c42631 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -118,7 +118,7 @@ WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTa
118 : mutex_address(mutex_address) { 118 : mutex_address(mutex_address) {
119 mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); 119 mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address);
120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); 120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask);
121 owner = SharedFrom(handle_table.Get<Kernel::KThread>(owner_handle)); 121 owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe();
122} 122}
123 123
124WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; 124WaitTreeMutexInfo::~WaitTreeMutexInfo() = default;
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 3da2fdfd2..bf8120a71 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -80,10 +80,10 @@ public:
80 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 80 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
81 81
82private: 82private:
83 VAddr mutex_address; 83 VAddr mutex_address{};
84 u32 mutex_value; 84 u32 mutex_value{};
85 Kernel::Handle owner_handle; 85 Kernel::Handle owner_handle{};
86 std::shared_ptr<Kernel::KThread> owner; 86 Kernel::KThread* owner{};
87}; 87};
88 88
89class WaitTreeCallstack : public WaitTreeExpandableItem { 89class WaitTreeCallstack : public WaitTreeExpandableItem {