mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 13:20:03 +00:00 
			
		
		
		
	Kernel: Move HandleTable to a separate file
This commit is contained in:
		
							parent
							
								
									64ecf81a3c
								
							
						
					
					
						commit
						be031989ee
					
				
					 18 changed files with 242 additions and 203 deletions
				
			
		|  | @ -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" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue