diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 77 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.h | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.h | 8 |
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 | ||
| 50 | ResultVal<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 | |||
| 94 | ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { | 50 | ResultCode 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 | ||
| 121 | ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | 77 | ResultVal<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 | ||
| 130 | bool HandleTable::Remove(Handle handle) { | 90 | bool 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) { | |||
| 155 | bool HandleTable::IsValid(Handle handle) const { | 110 | bool 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 | ||
| 162 | Object* 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 | |||
| 175 | void HandleTable::Clear() { | 117 | void 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 | ||
| 204 | private: | 181 | private: |
| 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 | ||
| 21 | union ResultCode; | 21 | union 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 | ||
| 124 | WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; | 124 | WaitTreeMutexInfo::~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 | ||
| 82 | private: | 82 | private: |
| 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 | ||
| 89 | class WaitTreeCallstack : public WaitTreeExpandableItem { | 89 | class WaitTreeCallstack : public WaitTreeExpandableItem { |