From be031989ee9384786fb9ed380dab9a260ad69fd5 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Mon, 29 May 2017 16:45:42 -0700 Subject: Kernel: Move HandleTable to a separate file --- src/core/CMakeLists.txt | 2 + src/core/hle/ipc_helpers.h | 2 + src/core/hle/kernel/address_arbiter.h | 1 + src/core/hle/kernel/client_port.h | 1 + src/core/hle/kernel/client_session.h | 3 +- src/core/hle/kernel/handle_table.cpp | 97 +++++++++++++++++++++++++ src/core/hle/kernel/handle_table.h | 126 +++++++++++++++++++++++++++++++++ src/core/hle/kernel/kernel.cpp | 85 +--------------------- src/core/hle/kernel/kernel.h | 116 +----------------------------- src/core/hle/kernel/memory.cpp | 1 + src/core/hle/kernel/resource_limit.cpp | 1 + src/core/hle/kernel/semaphore.h | 1 + src/core/hle/kernel/server_session.h | 2 +- src/core/hle/kernel/thread.cpp | 1 + src/core/hle/kernel/timer.cpp | 1 + src/core/hle/service/apt/apt.h | 2 + src/core/hle/service/service.h | 1 - src/core/hle/svc.cpp | 2 + 18 files changed, 242 insertions(+), 203 deletions(-) create mode 100644 src/core/hle/kernel/handle_table.cpp create mode 100644 src/core/hle/kernel/handle_table.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ba24a6e02..bc3b429b3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -45,6 +45,7 @@ set(SRCS hle/kernel/client_port.cpp hle/kernel/client_session.cpp hle/kernel/event.cpp + hle/kernel/handle_table.cpp hle/kernel/kernel.cpp hle/kernel/memory.cpp hle/kernel/mutex.cpp @@ -237,6 +238,7 @@ set(HEADERS hle/kernel/client_session.h hle/kernel/errors.h hle/kernel/event.h + hle/kernel/handle_table.h hle/kernel/kernel.h hle/kernel/memory.h hle/kernel/mutex.h diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 06c4c5a85..d7348c09d 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -3,7 +3,9 @@ // Refer to the license.txt file included. #pragma once + #include "core/hle/ipc.h" +#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" namespace IPC { 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 @@ #include "common/common_types.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 // 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 @@ #include #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" namespace Kernel { 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 @@ #include #include - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" namespace Kernel { 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 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#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 HandleTable::Create(SharedPtr 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); +} + +ResultVal HandleTable::Duplicate(Handle handle) { + SharedPtr 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 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 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 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#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 Create(SharedPtr 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 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 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 + SharedPtr Get(Handle handle) const { + return DynamicObjectCast(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, 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 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 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 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include -#include "common/assert.h" -#include "common/logging/log.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/memory.h" #include "core/hle/kernel/process.h" @@ -18,86 +15,6 @@ namespace Kernel { unsigned int Object::next_object_id; -HandleTable g_handle_table; - -HandleTable::HandleTable() { - next_generation = 1; - Clear(); -} - -ResultVal HandleTable::Create(SharedPtr 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); -} - -ResultVal HandleTable::Duplicate(Handle handle) { - SharedPtr 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 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 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 @@ #pragma once -#include -#include #include #include -#include +#include #include #include "common/common_types.h" -#include "core/hle/result.h" namespace Kernel { using Handle = u32; -enum KernelHandle : Handle { - CurrentThread = 0xFFFF8000, - CurrentProcess = 0xFFFF8001, -}; - enum class HandleType : u32 { Unknown, Event, @@ -131,112 +123,6 @@ inline SharedPtr DynamicObjectCast(SharedPtr object) { 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 Create(SharedPtr 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 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 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 - SharedPtr Get(Handle handle) const { - return DynamicObjectCast(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, 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 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. void Init(u32 system_mode); 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 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include #include 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 @@ // Refer to the license.txt file included. #include +#include "common/assert.h" #include "common/logging/log.h" #include "core/hle/kernel/resource_limit.h" 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 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/wait_object.h" +#include "core/hle/result.h" namespace Kernel { 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 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/session.h" -#include "core/hle/kernel/thread.h" #include "core/hle/kernel/wait_object.h" #include "core/hle/result.h" #include "core/hle/service/service.h" @@ -21,6 +20,7 @@ namespace Kernel { class ClientSession; class ClientPort; class ServerSession; +class Thread; /** * 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 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/errors.h" +#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" #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 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/core_timing.h" +#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index e63b61450..ee80926d2 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -4,6 +4,8 @@ #pragma once +#include +#include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" #include "core/hle/kernel/kernel.h" diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index e6a5f1417..ffabc24a4 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -12,7 +12,6 @@ #include "core/hle/ipc.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/thread.h" #include "core/hle/result.h" #include "core/memory.h" diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 83767677f..e68b9f16a 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include #include "common/logging/log.h" @@ -16,6 +17,7 @@ #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/process.h" -- cgit v1.2.3