Kernel: Move HandleTable to a separate file
This commit is contained in:
		| @@ -45,6 +45,7 @@ set(SRCS | |||||||
|             hle/kernel/client_port.cpp |             hle/kernel/client_port.cpp | ||||||
|             hle/kernel/client_session.cpp |             hle/kernel/client_session.cpp | ||||||
|             hle/kernel/event.cpp |             hle/kernel/event.cpp | ||||||
|  |             hle/kernel/handle_table.cpp | ||||||
|             hle/kernel/kernel.cpp |             hle/kernel/kernel.cpp | ||||||
|             hle/kernel/memory.cpp |             hle/kernel/memory.cpp | ||||||
|             hle/kernel/mutex.cpp |             hle/kernel/mutex.cpp | ||||||
| @@ -237,6 +238,7 @@ set(HEADERS | |||||||
|             hle/kernel/client_session.h |             hle/kernel/client_session.h | ||||||
|             hle/kernel/errors.h |             hle/kernel/errors.h | ||||||
|             hle/kernel/event.h |             hle/kernel/event.h | ||||||
|  |             hle/kernel/handle_table.h | ||||||
|             hle/kernel/kernel.h |             hle/kernel/kernel.h | ||||||
|             hle/kernel/memory.h |             hle/kernel/memory.h | ||||||
|             hle/kernel/mutex.h |             hle/kernel/mutex.h | ||||||
|   | |||||||
| @@ -3,7 +3,9 @@ | |||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
|  | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  |  | ||||||
| namespace IPC { | namespace IPC { | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| // Address arbiters are an underlying kernel synchronization object that can be created/used via | // Address arbiters are an underlying kernel synchronization object that can be created/used via | ||||||
| // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR | // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,10 +6,9 @@ | |||||||
|  |  | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  |  | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										97
									
								
								src/core/hle/kernel/handle_table.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/core/hle/kernel/handle_table.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <utility> | ||||||
|  | #include "common/assert.h" | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "core/hle/kernel/errors.h" | ||||||
|  | #include "core/hle/kernel/handle_table.h" | ||||||
|  | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/kernel/thread.h" | ||||||
|  |  | ||||||
|  | namespace Kernel { | ||||||
|  |  | ||||||
|  | HandleTable g_handle_table; | ||||||
|  |  | ||||||
|  | HandleTable::HandleTable() { | ||||||
|  |     next_generation = 1; | ||||||
|  |     Clear(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | ||||||
|  |     DEBUG_ASSERT(obj != nullptr); | ||||||
|  |  | ||||||
|  |     u16 slot = next_free_slot; | ||||||
|  |     if (slot >= generations.size()) { | ||||||
|  |         LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); | ||||||
|  |         return ERR_OUT_OF_HANDLES; | ||||||
|  |     } | ||||||
|  |     next_free_slot = generations[slot]; | ||||||
|  |  | ||||||
|  |     u16 generation = next_generation++; | ||||||
|  |  | ||||||
|  |     // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | ||||||
|  |     // CTR-OS doesn't use generation 0, so skip straight to 1. | ||||||
|  |     if (next_generation >= (1 << 15)) | ||||||
|  |         next_generation = 1; | ||||||
|  |  | ||||||
|  |     generations[slot] = generation; | ||||||
|  |     objects[slot] = std::move(obj); | ||||||
|  |  | ||||||
|  |     Handle handle = generation | (slot << 15); | ||||||
|  |     return MakeResult<Handle>(handle); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | ||||||
|  |     SharedPtr<Object> object = GetGeneric(handle); | ||||||
|  |     if (object == nullptr) { | ||||||
|  |         LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); | ||||||
|  |         return ERR_INVALID_HANDLE; | ||||||
|  |     } | ||||||
|  |     return Create(std::move(object)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultCode HandleTable::Close(Handle handle) { | ||||||
|  |     if (!IsValid(handle)) | ||||||
|  |         return ERR_INVALID_HANDLE; | ||||||
|  |  | ||||||
|  |     u16 slot = GetSlot(handle); | ||||||
|  |  | ||||||
|  |     objects[slot] = nullptr; | ||||||
|  |  | ||||||
|  |     generations[slot] = next_free_slot; | ||||||
|  |     next_free_slot = slot; | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool HandleTable::IsValid(Handle handle) const { | ||||||
|  |     size_t slot = GetSlot(handle); | ||||||
|  |     u16 generation = GetGeneration(handle); | ||||||
|  |  | ||||||
|  |     return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { | ||||||
|  |     if (handle == CurrentThread) { | ||||||
|  |         return GetCurrentThread(); | ||||||
|  |     } else if (handle == CurrentProcess) { | ||||||
|  |         return g_current_process; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!IsValid(handle)) { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |     return objects[GetSlot(handle)]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HandleTable::Clear() { | ||||||
|  |     for (u16 i = 0; i < MAX_COUNT; ++i) { | ||||||
|  |         generations[i] = i + 1; | ||||||
|  |         objects[i] = nullptr; | ||||||
|  |     } | ||||||
|  |     next_free_slot = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
							
								
								
									
										126
									
								
								src/core/hle/kernel/handle_table.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/core/hle/kernel/handle_table.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <array> | ||||||
|  | #include <cstddef> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
|  | namespace Kernel { | ||||||
|  |  | ||||||
|  | enum KernelHandle : Handle { | ||||||
|  |     CurrentThread = 0xFFFF8000, | ||||||
|  |     CurrentProcess = 0xFFFF8001, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class allows the creation of Handles, which are references to objects that can be tested | ||||||
|  |  * for validity and looked up. Here they are used to pass references to kernel objects to/from the | ||||||
|  |  * emulated process. it has been designed so that it follows the same handle format and has | ||||||
|  |  * approximately the same restrictions as the handle manager in the CTR-OS. | ||||||
|  |  * | ||||||
|  |  * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0). | ||||||
|  |  * The slot index is used to index into the arrays in this class to access the data corresponding | ||||||
|  |  * to the Handle. | ||||||
|  |  * | ||||||
|  |  * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter | ||||||
|  |  * is kept and incremented every time a Handle is created. This is the Handle's "generation". The | ||||||
|  |  * value of the counter is stored into the Handle as well as in the handle table (in the | ||||||
|  |  * "generations" array). When looking up a handle, the Handle's generation must match with the | ||||||
|  |  * value stored on the class, otherwise the Handle is considered invalid. | ||||||
|  |  * | ||||||
|  |  * To find free slots when allocating a Handle without needing to scan the entire object array, the | ||||||
|  |  * generations field of unallocated slots is re-purposed as a linked list of indices to free slots. | ||||||
|  |  * When a Handle is created, an index is popped off the list and used for the new Handle. When it | ||||||
|  |  * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is | ||||||
|  |  * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been | ||||||
|  |  * verified and isn't likely to cause any problems. | ||||||
|  |  */ | ||||||
|  | class HandleTable final : NonCopyable { | ||||||
|  | public: | ||||||
|  |     HandleTable(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Allocates a handle for the given object. | ||||||
|  |      * @return The created Handle or one of the following errors: | ||||||
|  |      *           - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. | ||||||
|  |      */ | ||||||
|  |     ResultVal<Handle> Create(SharedPtr<Object> obj); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns a new handle that points to the same object as the passed in handle. | ||||||
|  |      * @return The duplicated Handle or one of the following errors: | ||||||
|  |      *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||||||
|  |      *           - Any errors returned by `Create()`. | ||||||
|  |      */ | ||||||
|  |     ResultVal<Handle> Duplicate(Handle handle); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Closes a handle, removing it from the table and decreasing the object's ref-count. | ||||||
|  |      * @return `RESULT_SUCCESS` or one of the following errors: | ||||||
|  |      *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||||||
|  |      */ | ||||||
|  |     ResultCode Close(Handle handle); | ||||||
|  |  | ||||||
|  |     /// Checks if a handle is valid and points to an existing object. | ||||||
|  |     bool IsValid(Handle handle) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Looks up a handle. | ||||||
|  |      * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. | ||||||
|  |      */ | ||||||
|  |     SharedPtr<Object> GetGeneric(Handle handle) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Looks up a handle while verifying its type. | ||||||
|  |      * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its | ||||||
|  |      *         type differs from the requested one. | ||||||
|  |      */ | ||||||
|  |     template <class T> | ||||||
|  |     SharedPtr<T> Get(Handle handle) const { | ||||||
|  |         return DynamicObjectCast<T>(GetGeneric(handle)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Closes all handles held in this table. | ||||||
|  |     void Clear(); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** | ||||||
|  |      * This is the maximum limit of handles allowed per process in CTR-OS. It can be further | ||||||
|  |      * reduced by ExHeader values, but this is not emulated here. | ||||||
|  |      */ | ||||||
|  |     static const size_t MAX_COUNT = 4096; | ||||||
|  |  | ||||||
|  |     static u16 GetSlot(Handle handle) { | ||||||
|  |         return handle >> 15; | ||||||
|  |     } | ||||||
|  |     static u16 GetGeneration(Handle handle) { | ||||||
|  |         return handle & 0x7FFF; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Stores the Object referenced by the handle or null if the slot is empty. | ||||||
|  |     std::array<SharedPtr<Object>, MAX_COUNT> objects; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The value of `next_generation` when the handle was created, used to check for validity. For | ||||||
|  |      * empty slots, contains the index of the next free slot in the list. | ||||||
|  |      */ | ||||||
|  |     std::array<u16, MAX_COUNT> generations; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Global counter of the number of created handles. Stored in `generations` when a handle is | ||||||
|  |      * created, and wraps around to 1 when it hits 0x8000. | ||||||
|  |      */ | ||||||
|  |     u16 next_generation; | ||||||
|  |  | ||||||
|  |     /// Head of the free slots linked list. | ||||||
|  |     u16 next_free_slot; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | extern HandleTable g_handle_table; | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
| @@ -2,11 +2,8 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
| #include <algorithm> |  | ||||||
| #include "common/assert.h" |  | ||||||
| #include "common/logging/log.h" |  | ||||||
| #include "core/hle/config_mem.h" | #include "core/hle/config_mem.h" | ||||||
| #include "core/hle/kernel/errors.h" | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| @@ -18,86 +15,6 @@ | |||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
| unsigned int Object::next_object_id; | unsigned int Object::next_object_id; | ||||||
| HandleTable g_handle_table; |  | ||||||
|  |  | ||||||
| HandleTable::HandleTable() { |  | ||||||
|     next_generation = 1; |  | ||||||
|     Clear(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { |  | ||||||
|     DEBUG_ASSERT(obj != nullptr); |  | ||||||
|  |  | ||||||
|     u16 slot = next_free_slot; |  | ||||||
|     if (slot >= generations.size()) { |  | ||||||
|         LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); |  | ||||||
|         return ERR_OUT_OF_HANDLES; |  | ||||||
|     } |  | ||||||
|     next_free_slot = generations[slot]; |  | ||||||
|  |  | ||||||
|     u16 generation = next_generation++; |  | ||||||
|  |  | ||||||
|     // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. |  | ||||||
|     // CTR-OS doesn't use generation 0, so skip straight to 1. |  | ||||||
|     if (next_generation >= (1 << 15)) |  | ||||||
|         next_generation = 1; |  | ||||||
|  |  | ||||||
|     generations[slot] = generation; |  | ||||||
|     objects[slot] = std::move(obj); |  | ||||||
|  |  | ||||||
|     Handle handle = generation | (slot << 15); |  | ||||||
|     return MakeResult<Handle>(handle); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ResultVal<Handle> HandleTable::Duplicate(Handle handle) { |  | ||||||
|     SharedPtr<Object> object = GetGeneric(handle); |  | ||||||
|     if (object == nullptr) { |  | ||||||
|         LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); |  | ||||||
|         return ERR_INVALID_HANDLE; |  | ||||||
|     } |  | ||||||
|     return Create(std::move(object)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ResultCode HandleTable::Close(Handle handle) { |  | ||||||
|     if (!IsValid(handle)) |  | ||||||
|         return ERR_INVALID_HANDLE; |  | ||||||
|  |  | ||||||
|     u16 slot = GetSlot(handle); |  | ||||||
|  |  | ||||||
|     objects[slot] = nullptr; |  | ||||||
|  |  | ||||||
|     generations[slot] = next_free_slot; |  | ||||||
|     next_free_slot = slot; |  | ||||||
|     return RESULT_SUCCESS; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool HandleTable::IsValid(Handle handle) const { |  | ||||||
|     size_t slot = GetSlot(handle); |  | ||||||
|     u16 generation = GetGeneration(handle); |  | ||||||
|  |  | ||||||
|     return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { |  | ||||||
|     if (handle == CurrentThread) { |  | ||||||
|         return GetCurrentThread(); |  | ||||||
|     } else if (handle == CurrentProcess) { |  | ||||||
|         return g_current_process; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!IsValid(handle)) { |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     return objects[GetSlot(handle)]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void HandleTable::Clear() { |  | ||||||
|     for (u16 i = 0; i < MAX_COUNT; ++i) { |  | ||||||
|         generations[i] = i + 1; |  | ||||||
|         objects[i] = nullptr; |  | ||||||
|     } |  | ||||||
|     next_free_slot = 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Initialize the kernel | /// Initialize the kernel | ||||||
| void Init(u32 system_mode) { | void Init(u32 system_mode) { | ||||||
|   | |||||||
| @@ -4,24 +4,16 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <algorithm> |  | ||||||
| #include <array> |  | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <utility> | ||||||
| #include <boost/smart_ptr/intrusive_ptr.hpp> | #include <boost/smart_ptr/intrusive_ptr.hpp> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/result.h" |  | ||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
| using Handle = u32; | using Handle = u32; | ||||||
|  |  | ||||||
| enum KernelHandle : Handle { |  | ||||||
|     CurrentThread = 0xFFFF8000, |  | ||||||
|     CurrentProcess = 0xFFFF8001, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum class HandleType : u32 { | enum class HandleType : u32 { | ||||||
|     Unknown, |     Unknown, | ||||||
|     Event, |     Event, | ||||||
| @@ -131,112 +123,6 @@ inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) { | |||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * This class allows the creation of Handles, which are references to objects that can be tested |  | ||||||
|  * for validity and looked up. Here they are used to pass references to kernel objects to/from the |  | ||||||
|  * emulated process. it has been designed so that it follows the same handle format and has |  | ||||||
|  * approximately the same restrictions as the handle manager in the CTR-OS. |  | ||||||
|  * |  | ||||||
|  * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0). |  | ||||||
|  * The slot index is used to index into the arrays in this class to access the data corresponding |  | ||||||
|  * to the Handle. |  | ||||||
|  * |  | ||||||
|  * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter |  | ||||||
|  * is kept and incremented every time a Handle is created. This is the Handle's "generation". The |  | ||||||
|  * value of the counter is stored into the Handle as well as in the handle table (in the |  | ||||||
|  * "generations" array). When looking up a handle, the Handle's generation must match with the |  | ||||||
|  * value stored on the class, otherwise the Handle is considered invalid. |  | ||||||
|  * |  | ||||||
|  * To find free slots when allocating a Handle without needing to scan the entire object array, the |  | ||||||
|  * generations field of unallocated slots is re-purposed as a linked list of indices to free slots. |  | ||||||
|  * When a Handle is created, an index is popped off the list and used for the new Handle. When it |  | ||||||
|  * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is |  | ||||||
|  * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been |  | ||||||
|  * verified and isn't likely to cause any problems. |  | ||||||
|  */ |  | ||||||
| class HandleTable final : NonCopyable { |  | ||||||
| public: |  | ||||||
|     HandleTable(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Allocates a handle for the given object. |  | ||||||
|      * @return The created Handle or one of the following errors: |  | ||||||
|      *           - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. |  | ||||||
|      */ |  | ||||||
|     ResultVal<Handle> Create(SharedPtr<Object> obj); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns a new handle that points to the same object as the passed in handle. |  | ||||||
|      * @return The duplicated Handle or one of the following errors: |  | ||||||
|      *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in. |  | ||||||
|      *           - Any errors returned by `Create()`. |  | ||||||
|      */ |  | ||||||
|     ResultVal<Handle> Duplicate(Handle handle); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Closes a handle, removing it from the table and decreasing the object's ref-count. |  | ||||||
|      * @return `RESULT_SUCCESS` or one of the following errors: |  | ||||||
|      *           - `ERR_INVALID_HANDLE`: an invalid handle was passed in. |  | ||||||
|      */ |  | ||||||
|     ResultCode Close(Handle handle); |  | ||||||
|  |  | ||||||
|     /// Checks if a handle is valid and points to an existing object. |  | ||||||
|     bool IsValid(Handle handle) const; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Looks up a handle. |  | ||||||
|      * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. |  | ||||||
|      */ |  | ||||||
|     SharedPtr<Object> GetGeneric(Handle handle) const; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Looks up a handle while verifying its type. |  | ||||||
|      * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its |  | ||||||
|      *         type differs from the requested one. |  | ||||||
|      */ |  | ||||||
|     template <class T> |  | ||||||
|     SharedPtr<T> Get(Handle handle) const { |  | ||||||
|         return DynamicObjectCast<T>(GetGeneric(handle)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Closes all handles held in this table. |  | ||||||
|     void Clear(); |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     /** |  | ||||||
|      * This is the maximum limit of handles allowed per process in CTR-OS. It can be further |  | ||||||
|      * reduced by ExHeader values, but this is not emulated here. |  | ||||||
|      */ |  | ||||||
|     static const size_t MAX_COUNT = 4096; |  | ||||||
|  |  | ||||||
|     static u16 GetSlot(Handle handle) { |  | ||||||
|         return handle >> 15; |  | ||||||
|     } |  | ||||||
|     static u16 GetGeneration(Handle handle) { |  | ||||||
|         return handle & 0x7FFF; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Stores the Object referenced by the handle or null if the slot is empty. |  | ||||||
|     std::array<SharedPtr<Object>, MAX_COUNT> objects; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * The value of `next_generation` when the handle was created, used to check for validity. For |  | ||||||
|      * empty slots, contains the index of the next free slot in the list. |  | ||||||
|      */ |  | ||||||
|     std::array<u16, MAX_COUNT> generations; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Global counter of the number of created handles. Stored in `generations` when a handle is |  | ||||||
|      * created, and wraps around to 1 when it hits 0x8000. |  | ||||||
|      */ |  | ||||||
|     u16 next_generation; |  | ||||||
|  |  | ||||||
|     /// Head of the free slots linked list. |  | ||||||
|     u16 next_free_slot; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| extern HandleTable g_handle_table; |  | ||||||
|  |  | ||||||
| /// Initialize the kernel with the specified system mode. | /// Initialize the kernel with the specified system mode. | ||||||
| void Init(u32 system_mode); | void Init(u32 system_mode); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <algorithm> | ||||||
| #include <cinttypes> | #include <cinttypes> | ||||||
| #include <map> | #include <map> | ||||||
| #include <memory> | #include <memory> | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/hle/kernel/resource_limit.h" | #include "core/hle/kernel/resource_limit.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/wait_object.h" | #include "core/hle/kernel/wait_object.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/session.h" | #include "core/hle/kernel/session.h" | ||||||
| #include "core/hle/kernel/thread.h" |  | ||||||
| #include "core/hle/kernel/wait_object.h" | #include "core/hle/kernel/wait_object.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| @@ -21,6 +20,7 @@ namespace Kernel { | |||||||
| class ClientSession; | class ClientSession; | ||||||
| class ClientPort; | class ClientPort; | ||||||
| class ServerSession; | class ServerSession; | ||||||
|  | class Thread; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS |  * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ | |||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/kernel/errors.h" | #include "core/hle/kernel/errors.h" | ||||||
|  | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/mutex.h" | #include "core/hle/kernel/mutex.h" | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
|  | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/kernel/timer.h" | #include "core/hle/kernel/timer.h" | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/swap.h" | #include "common/swap.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ | |||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/kernel/client_port.h" | #include "core/hle/kernel/client_port.h" | ||||||
| #include "core/hle/kernel/thread.h" |  | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <algorithm> | ||||||
| #include <cinttypes> | #include <cinttypes> | ||||||
| #include <map> | #include <map> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| @@ -16,6 +17,7 @@ | |||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
| #include "core/hle/kernel/errors.h" | #include "core/hle/kernel/errors.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
|  | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/mutex.h" | #include "core/hle/kernel/mutex.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user