diff options
| author | 2017-05-29 16:45:42 -0700 | |
|---|---|---|
| committer | 2017-05-29 17:34:39 -0700 | |
| commit | be031989ee9384786fb9ed380dab9a260ad69fd5 (patch) | |
| tree | 875d7725802afed2849be9ca6947f129b0b60134 /src/core/hle/kernel | |
| parent | Kernel: Move WaitObject to a separate file (diff) | |
| download | yuzu-be031989ee9384786fb9ed380dab9a260ad69fd5.tar.gz yuzu-be031989ee9384786fb9ed380dab9a260ad69fd5.tar.xz yuzu-be031989ee9384786fb9ed380dab9a260ad69fd5.zip | |
Kernel: Move HandleTable to a separate file
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_port.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/client_session.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 97 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.h | 126 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 85 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 116 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/resource_limit.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/timer.cpp | 1 |
13 files changed, 234 insertions, 202 deletions
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 6a7af93a9..1d24401b1 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/hle/kernel/kernel.h" | 8 | #include "core/hle/kernel/kernel.h" |
| 9 | #include "core/hle/result.h" | ||
| 9 | 10 | ||
| 10 | // Address arbiters are an underlying kernel synchronization object that can be created/used via | 11 | // Address arbiters are an underlying kernel synchronization object that can be created/used via |
| 11 | // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR | 12 | // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR |
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 511490c7c..8f7d6ac44 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/hle/kernel/kernel.h" | 9 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/result.h" | ||
| 10 | 11 | ||
| 11 | namespace Kernel { | 12 | namespace Kernel { |
| 12 | 13 | ||
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index 9f3adb72b..2de379c09 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h | |||
| @@ -6,10 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | |||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 11 | |||
| 12 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/result.h" | ||
| 13 | 12 | ||
| 14 | namespace Kernel { | 13 | namespace Kernel { |
| 15 | 14 | ||
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp new file mode 100644 index 000000000..c7322d883 --- /dev/null +++ b/src/core/hle/kernel/handle_table.cpp | |||
| @@ -0,0 +1,97 @@ | |||
| 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/hle/kernel/errors.h" | ||
| 9 | #include "core/hle/kernel/handle_table.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/kernel/process.h" | ||
| 12 | #include "core/hle/kernel/thread.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | HandleTable g_handle_table; | ||
| 17 | |||
| 18 | HandleTable::HandleTable() { | ||
| 19 | next_generation = 1; | ||
| 20 | Clear(); | ||
| 21 | } | ||
| 22 | |||
| 23 | ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | ||
| 24 | DEBUG_ASSERT(obj != nullptr); | ||
| 25 | |||
| 26 | u16 slot = next_free_slot; | ||
| 27 | if (slot >= generations.size()) { | ||
| 28 | LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); | ||
| 29 | return ERR_OUT_OF_HANDLES; | ||
| 30 | } | ||
| 31 | next_free_slot = generations[slot]; | ||
| 32 | |||
| 33 | u16 generation = next_generation++; | ||
| 34 | |||
| 35 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | ||
| 36 | // CTR-OS doesn't use generation 0, so skip straight to 1. | ||
| 37 | if (next_generation >= (1 << 15)) | ||
| 38 | next_generation = 1; | ||
| 39 | |||
| 40 | generations[slot] = generation; | ||
| 41 | objects[slot] = std::move(obj); | ||
| 42 | |||
| 43 | Handle handle = generation | (slot << 15); | ||
| 44 | return MakeResult<Handle>(handle); | ||
| 45 | } | ||
| 46 | |||
| 47 | ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | ||
| 48 | SharedPtr<Object> object = GetGeneric(handle); | ||
| 49 | if (object == nullptr) { | ||
| 50 | LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); | ||
| 51 | return ERR_INVALID_HANDLE; | ||
| 52 | } | ||
| 53 | return Create(std::move(object)); | ||
| 54 | } | ||
| 55 | |||
| 56 | ResultCode HandleTable::Close(Handle handle) { | ||
| 57 | if (!IsValid(handle)) | ||
| 58 | return ERR_INVALID_HANDLE; | ||
| 59 | |||
| 60 | u16 slot = GetSlot(handle); | ||
| 61 | |||
| 62 | objects[slot] = nullptr; | ||
| 63 | |||
| 64 | generations[slot] = next_free_slot; | ||
| 65 | next_free_slot = slot; | ||
| 66 | return RESULT_SUCCESS; | ||
| 67 | } | ||
| 68 | |||
| 69 | bool HandleTable::IsValid(Handle handle) const { | ||
| 70 | size_t slot = GetSlot(handle); | ||
| 71 | u16 generation = GetGeneration(handle); | ||
| 72 | |||
| 73 | return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; | ||
| 74 | } | ||
| 75 | |||
| 76 | SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { | ||
| 77 | if (handle == CurrentThread) { | ||
| 78 | return GetCurrentThread(); | ||
| 79 | } else if (handle == CurrentProcess) { | ||
| 80 | return g_current_process; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (!IsValid(handle)) { | ||
| 84 | return nullptr; | ||
| 85 | } | ||
| 86 | return objects[GetSlot(handle)]; | ||
| 87 | } | ||
| 88 | |||
| 89 | void HandleTable::Clear() { | ||
| 90 | for (u16 i = 0; i < MAX_COUNT; ++i) { | ||
| 91 | generations[i] = i + 1; | ||
| 92 | objects[i] = nullptr; | ||
| 93 | } | ||
| 94 | next_free_slot = 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | } // namespace | ||
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h new file mode 100644 index 000000000..d6aaefbf7 --- /dev/null +++ b/src/core/hle/kernel/handle_table.h | |||
| @@ -0,0 +1,126 @@ | |||
| 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 "common/common_types.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | enum KernelHandle : Handle { | ||
| 16 | CurrentThread = 0xFFFF8000, | ||
| 17 | CurrentProcess = 0xFFFF8001, | ||
| 18 | }; | ||
| 19 | |||
| 20 | /** | ||
| 21 | * This class allows the creation of Handles, which are references to objects that can be tested | ||
| 22 | * for validity and looked up. Here they are used to pass references to kernel objects to/from the | ||
| 23 | * emulated process. it has been designed so that it follows the same handle format and has | ||
| 24 | * approximately the same restrictions as the handle manager in the CTR-OS. | ||
| 25 | * | ||
| 26 | * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0). | ||
| 27 | * The slot index is used to index into the arrays in this class to access the data corresponding | ||
| 28 | * to the Handle. | ||
| 29 | * | ||
| 30 | * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter | ||
| 31 | * is kept and incremented every time a Handle is created. This is the Handle's "generation". The | ||
| 32 | * value of the counter is stored into the Handle as well as in the handle table (in the | ||
| 33 | * "generations" array). When looking up a handle, the Handle's generation must match with the | ||
| 34 | * value stored on the class, otherwise the Handle is considered invalid. | ||
| 35 | * | ||
| 36 | * To find free slots when allocating a Handle without needing to scan the entire object array, the | ||
| 37 | * generations field of unallocated slots is re-purposed as a linked list of indices to free slots. | ||
| 38 | * When a Handle is created, an index is popped off the list and used for the new Handle. When it | ||
| 39 | * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is | ||
| 40 | * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been | ||
| 41 | * verified and isn't likely to cause any problems. | ||
| 42 | */ | ||
| 43 | class HandleTable final : NonCopyable { | ||
| 44 | public: | ||
| 45 | HandleTable(); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Allocates a handle for the given object. | ||
| 49 | * @return The created Handle or one of the following errors: | ||
| 50 | * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. | ||
| 51 | */ | ||
| 52 | ResultVal<Handle> Create(SharedPtr<Object> obj); | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Returns a new handle that points to the same object as the passed in handle. | ||
| 56 | * @return The duplicated Handle or one of the following errors: | ||
| 57 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 58 | * - Any errors returned by `Create()`. | ||
| 59 | */ | ||
| 60 | ResultVal<Handle> Duplicate(Handle handle); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Closes a handle, removing it from the table and decreasing the object's ref-count. | ||
| 64 | * @return `RESULT_SUCCESS` or one of the following errors: | ||
| 65 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 66 | */ | ||
| 67 | ResultCode Close(Handle handle); | ||
| 68 | |||
| 69 | /// Checks if a handle is valid and points to an existing object. | ||
| 70 | bool IsValid(Handle handle) const; | ||
| 71 | |||
| 72 | /** | ||
| 73 | * Looks up a handle. | ||
| 74 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. | ||
| 75 | */ | ||
| 76 | SharedPtr<Object> GetGeneric(Handle handle) const; | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Looks up a handle while verifying its type. | ||
| 80 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its | ||
| 81 | * type differs from the requested one. | ||
| 82 | */ | ||
| 83 | template <class T> | ||
| 84 | SharedPtr<T> Get(Handle handle) const { | ||
| 85 | return DynamicObjectCast<T>(GetGeneric(handle)); | ||
| 86 | } | ||
| 87 | |||
| 88 | /// Closes all handles held in this table. | ||
| 89 | void Clear(); | ||
| 90 | |||
| 91 | private: | ||
| 92 | /** | ||
| 93 | * This is the maximum limit of handles allowed per process in CTR-OS. It can be further | ||
| 94 | * reduced by ExHeader values, but this is not emulated here. | ||
| 95 | */ | ||
| 96 | static const size_t MAX_COUNT = 4096; | ||
| 97 | |||
| 98 | static u16 GetSlot(Handle handle) { | ||
| 99 | return handle >> 15; | ||
| 100 | } | ||
| 101 | static u16 GetGeneration(Handle handle) { | ||
| 102 | return handle & 0x7FFF; | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Stores the Object referenced by the handle or null if the slot is empty. | ||
| 106 | std::array<SharedPtr<Object>, MAX_COUNT> objects; | ||
| 107 | |||
| 108 | /** | ||
| 109 | * The value of `next_generation` when the handle was created, used to check for validity. For | ||
| 110 | * empty slots, contains the index of the next free slot in the list. | ||
| 111 | */ | ||
| 112 | std::array<u16, MAX_COUNT> generations; | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Global counter of the number of created handles. Stored in `generations` when a handle is | ||
| 116 | * created, and wraps around to 1 when it hits 0x8000. | ||
| 117 | */ | ||
| 118 | u16 next_generation; | ||
| 119 | |||
| 120 | /// Head of the free slots linked list. | ||
| 121 | u16 next_free_slot; | ||
| 122 | }; | ||
| 123 | |||
| 124 | extern HandleTable g_handle_table; | ||
| 125 | |||
| 126 | } // namespace | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b0af5b9b8..7470a97ca 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -2,11 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/logging/log.h" | ||
| 8 | #include "core/hle/config_mem.h" | 5 | #include "core/hle/config_mem.h" |
| 9 | #include "core/hle/kernel/errors.h" | 6 | #include "core/hle/kernel/handle_table.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 7 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/memory.h" | 8 | #include "core/hle/kernel/memory.h" |
| 12 | #include "core/hle/kernel/process.h" | 9 | #include "core/hle/kernel/process.h" |
| @@ -18,86 +15,6 @@ | |||
| 18 | namespace Kernel { | 15 | namespace Kernel { |
| 19 | 16 | ||
| 20 | unsigned int Object::next_object_id; | 17 | unsigned int Object::next_object_id; |
| 21 | HandleTable g_handle_table; | ||
| 22 | |||
| 23 | HandleTable::HandleTable() { | ||
| 24 | next_generation = 1; | ||
| 25 | Clear(); | ||
| 26 | } | ||
| 27 | |||
| 28 | ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | ||
| 29 | DEBUG_ASSERT(obj != nullptr); | ||
| 30 | |||
| 31 | u16 slot = next_free_slot; | ||
| 32 | if (slot >= generations.size()) { | ||
| 33 | LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); | ||
| 34 | return ERR_OUT_OF_HANDLES; | ||
| 35 | } | ||
| 36 | next_free_slot = generations[slot]; | ||
| 37 | |||
| 38 | u16 generation = next_generation++; | ||
| 39 | |||
| 40 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | ||
| 41 | // CTR-OS doesn't use generation 0, so skip straight to 1. | ||
| 42 | if (next_generation >= (1 << 15)) | ||
| 43 | next_generation = 1; | ||
| 44 | |||
| 45 | generations[slot] = generation; | ||
| 46 | objects[slot] = std::move(obj); | ||
| 47 | |||
| 48 | Handle handle = generation | (slot << 15); | ||
| 49 | return MakeResult<Handle>(handle); | ||
| 50 | } | ||
| 51 | |||
| 52 | ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | ||
| 53 | SharedPtr<Object> object = GetGeneric(handle); | ||
| 54 | if (object == nullptr) { | ||
| 55 | LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); | ||
| 56 | return ERR_INVALID_HANDLE; | ||
| 57 | } | ||
| 58 | return Create(std::move(object)); | ||
| 59 | } | ||
| 60 | |||
| 61 | ResultCode HandleTable::Close(Handle handle) { | ||
| 62 | if (!IsValid(handle)) | ||
| 63 | return ERR_INVALID_HANDLE; | ||
| 64 | |||
| 65 | u16 slot = GetSlot(handle); | ||
| 66 | |||
| 67 | objects[slot] = nullptr; | ||
| 68 | |||
| 69 | generations[slot] = next_free_slot; | ||
| 70 | next_free_slot = slot; | ||
| 71 | return RESULT_SUCCESS; | ||
| 72 | } | ||
| 73 | |||
| 74 | bool HandleTable::IsValid(Handle handle) const { | ||
| 75 | size_t slot = GetSlot(handle); | ||
| 76 | u16 generation = GetGeneration(handle); | ||
| 77 | |||
| 78 | return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; | ||
| 79 | } | ||
| 80 | |||
| 81 | SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { | ||
| 82 | if (handle == CurrentThread) { | ||
| 83 | return GetCurrentThread(); | ||
| 84 | } else if (handle == CurrentProcess) { | ||
| 85 | return g_current_process; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (!IsValid(handle)) { | ||
| 89 | return nullptr; | ||
| 90 | } | ||
| 91 | return objects[GetSlot(handle)]; | ||
| 92 | } | ||
| 93 | |||
| 94 | void HandleTable::Clear() { | ||
| 95 | for (u16 i = 0; i < MAX_COUNT; ++i) { | ||
| 96 | generations[i] = i + 1; | ||
| 97 | objects[i] = nullptr; | ||
| 98 | } | ||
| 99 | next_free_slot = 0; | ||
| 100 | } | ||
| 101 | 18 | ||
| 102 | /// Initialize the kernel | 19 | /// Initialize the kernel |
| 103 | void Init(u32 system_mode) { | 20 | void Init(u32 system_mode) { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5335a961d..9cf288b08 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -4,24 +4,16 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <algorithm> | ||
| 8 | #include <array> | ||
| 9 | #include <cstddef> | 7 | #include <cstddef> |
| 10 | #include <string> | 8 | #include <string> |
| 11 | #include <vector> | 9 | #include <utility> |
| 12 | #include <boost/smart_ptr/intrusive_ptr.hpp> | 10 | #include <boost/smart_ptr/intrusive_ptr.hpp> |
| 13 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 14 | #include "core/hle/result.h" | ||
| 15 | 12 | ||
| 16 | namespace Kernel { | 13 | namespace Kernel { |
| 17 | 14 | ||
| 18 | using Handle = u32; | 15 | using Handle = u32; |
| 19 | 16 | ||
| 20 | enum KernelHandle : Handle { | ||
| 21 | CurrentThread = 0xFFFF8000, | ||
| 22 | CurrentProcess = 0xFFFF8001, | ||
| 23 | }; | ||
| 24 | |||
| 25 | enum class HandleType : u32 { | 17 | enum class HandleType : u32 { |
| 26 | Unknown, | 18 | Unknown, |
| 27 | Event, | 19 | Event, |
| @@ -131,112 +123,6 @@ inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) { | |||
| 131 | return nullptr; | 123 | return nullptr; |
| 132 | } | 124 | } |
| 133 | 125 | ||
| 134 | /** | ||
| 135 | * This class allows the creation of Handles, which are references to objects that can be tested | ||
| 136 | * for validity and looked up. Here they are used to pass references to kernel objects to/from the | ||
| 137 | * emulated process. it has been designed so that it follows the same handle format and has | ||
| 138 | * approximately the same restrictions as the handle manager in the CTR-OS. | ||
| 139 | * | ||
| 140 | * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0). | ||
| 141 | * The slot index is used to index into the arrays in this class to access the data corresponding | ||
| 142 | * to the Handle. | ||
| 143 | * | ||
| 144 | * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter | ||
| 145 | * is kept and incremented every time a Handle is created. This is the Handle's "generation". The | ||
| 146 | * value of the counter is stored into the Handle as well as in the handle table (in the | ||
| 147 | * "generations" array). When looking up a handle, the Handle's generation must match with the | ||
| 148 | * value stored on the class, otherwise the Handle is considered invalid. | ||
| 149 | * | ||
| 150 | * To find free slots when allocating a Handle without needing to scan the entire object array, the | ||
| 151 | * generations field of unallocated slots is re-purposed as a linked list of indices to free slots. | ||
| 152 | * When a Handle is created, an index is popped off the list and used for the new Handle. When it | ||
| 153 | * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is | ||
| 154 | * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been | ||
| 155 | * verified and isn't likely to cause any problems. | ||
| 156 | */ | ||
| 157 | class HandleTable final : NonCopyable { | ||
| 158 | public: | ||
| 159 | HandleTable(); | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Allocates a handle for the given object. | ||
| 163 | * @return The created Handle or one of the following errors: | ||
| 164 | * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. | ||
| 165 | */ | ||
| 166 | ResultVal<Handle> Create(SharedPtr<Object> obj); | ||
| 167 | |||
| 168 | /** | ||
| 169 | * Returns a new handle that points to the same object as the passed in handle. | ||
| 170 | * @return The duplicated Handle or one of the following errors: | ||
| 171 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 172 | * - Any errors returned by `Create()`. | ||
| 173 | */ | ||
| 174 | ResultVal<Handle> Duplicate(Handle handle); | ||
| 175 | |||
| 176 | /** | ||
| 177 | * Closes a handle, removing it from the table and decreasing the object's ref-count. | ||
| 178 | * @return `RESULT_SUCCESS` or one of the following errors: | ||
| 179 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 180 | */ | ||
| 181 | ResultCode Close(Handle handle); | ||
| 182 | |||
| 183 | /// Checks if a handle is valid and points to an existing object. | ||
| 184 | bool IsValid(Handle handle) const; | ||
| 185 | |||
| 186 | /** | ||
| 187 | * Looks up a handle. | ||
| 188 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. | ||
| 189 | */ | ||
| 190 | SharedPtr<Object> GetGeneric(Handle handle) const; | ||
| 191 | |||
| 192 | /** | ||
| 193 | * Looks up a handle while verifying its type. | ||
| 194 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its | ||
| 195 | * type differs from the requested one. | ||
| 196 | */ | ||
| 197 | template <class T> | ||
| 198 | SharedPtr<T> Get(Handle handle) const { | ||
| 199 | return DynamicObjectCast<T>(GetGeneric(handle)); | ||
| 200 | } | ||
| 201 | |||
| 202 | /// Closes all handles held in this table. | ||
| 203 | void Clear(); | ||
| 204 | |||
| 205 | private: | ||
| 206 | /** | ||
| 207 | * This is the maximum limit of handles allowed per process in CTR-OS. It can be further | ||
| 208 | * reduced by ExHeader values, but this is not emulated here. | ||
| 209 | */ | ||
| 210 | static const size_t MAX_COUNT = 4096; | ||
| 211 | |||
| 212 | static u16 GetSlot(Handle handle) { | ||
| 213 | return handle >> 15; | ||
| 214 | } | ||
| 215 | static u16 GetGeneration(Handle handle) { | ||
| 216 | return handle & 0x7FFF; | ||
| 217 | } | ||
| 218 | |||
| 219 | /// Stores the Object referenced by the handle or null if the slot is empty. | ||
| 220 | std::array<SharedPtr<Object>, MAX_COUNT> objects; | ||
| 221 | |||
| 222 | /** | ||
| 223 | * The value of `next_generation` when the handle was created, used to check for validity. For | ||
| 224 | * empty slots, contains the index of the next free slot in the list. | ||
| 225 | */ | ||
| 226 | std::array<u16, MAX_COUNT> generations; | ||
| 227 | |||
| 228 | /** | ||
| 229 | * Global counter of the number of created handles. Stored in `generations` when a handle is | ||
| 230 | * created, and wraps around to 1 when it hits 0x8000. | ||
| 231 | */ | ||
| 232 | u16 next_generation; | ||
| 233 | |||
| 234 | /// Head of the free slots linked list. | ||
| 235 | u16 next_free_slot; | ||
| 236 | }; | ||
| 237 | |||
| 238 | extern HandleTable g_handle_table; | ||
| 239 | |||
| 240 | /// Initialize the kernel with the specified system mode. | 126 | /// Initialize the kernel with the specified system mode. |
| 241 | void Init(u32 system_mode); | 127 | void Init(u32 system_mode); |
| 242 | 128 | ||
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 8250a90b5..804f23b1c 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <cinttypes> | 6 | #include <cinttypes> |
| 6 | #include <map> | 7 | #include <map> |
| 7 | #include <memory> | 8 | #include <memory> |
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 3f51bc5de..a8f10a3ee 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/assert.h" | ||
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/hle/kernel/resource_limit.h" | 8 | #include "core/hle/kernel/resource_limit.h" |
| 8 | 9 | ||
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index ca6f908aa..7b0cacf2e 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/wait_object.h" | 11 | #include "core/hle/kernel/wait_object.h" |
| 12 | #include "core/hle/result.h" | ||
| 12 | 13 | ||
| 13 | namespace Kernel { | 14 | namespace Kernel { |
| 14 | 15 | ||
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 315b80d14..f1b76d8aa 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/kernel/session.h" | 12 | #include "core/hle/kernel/session.h" |
| 13 | #include "core/hle/kernel/thread.h" | ||
| 14 | #include "core/hle/kernel/wait_object.h" | 13 | #include "core/hle/kernel/wait_object.h" |
| 15 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/service.h" | 15 | #include "core/hle/service/service.h" |
| @@ -21,6 +20,7 @@ namespace Kernel { | |||
| 21 | class ClientSession; | 20 | class ClientSession; |
| 22 | class ClientPort; | 21 | class ClientPort; |
| 23 | class ServerSession; | 22 | class ServerSession; |
| 23 | class Thread; | ||
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS | 26 | * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 519ff51a8..75ce626f8 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 17 | #include "core/hle/kernel/errors.h" | 17 | #include "core/hle/kernel/errors.h" |
| 18 | #include "core/hle/kernel/handle_table.h" | ||
| 18 | #include "core/hle/kernel/kernel.h" | 19 | #include "core/hle/kernel/kernel.h" |
| 19 | #include "core/hle/kernel/memory.h" | 20 | #include "core/hle/kernel/memory.h" |
| 20 | #include "core/hle/kernel/mutex.h" | 21 | #include "core/hle/kernel/mutex.h" |
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index a00c75679..6f2cf3b02 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/hle/kernel/handle_table.h" | ||
| 9 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/kernel/thread.h" | 11 | #include "core/hle/kernel/thread.h" |
| 11 | #include "core/hle/kernel/timer.h" | 12 | #include "core/hle/kernel/timer.h" |