summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/handle_table.cpp
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-04-04 04:11:46 +0200
committerbunnei <bunneidev@gmail.com>2021-05-06 01:40:50 +0200
commitda7e9553dea4b1eaefb71aca8642ccce7c7f50fb (patch)
tree3da10a60005ddcc4237900eb5e7473fe7b006152 /src/core/hle/kernel/handle_table.cpp
parenthle: kernel: svc: Migrate GetThreadPriority, StartThread, and ExitThread. (diff)
downloadyuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.gz
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.bz2
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.lz
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.xz
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.zst
yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.zip
Diffstat (limited to 'src/core/hle/kernel/handle_table.cpp')
-rw-r--r--src/core/hle/kernel/handle_table.cpp48
1 files changed, 41 insertions, 7 deletions
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index f96d34078..8eec8a3b5 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -72,6 +72,33 @@ ResultVal<Handle> HandleTable::Create(std::shared_ptr<Object> obj) {
return MakeResult<Handle>(handle);
}
+ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
+ ASSERT(obj != nullptr);
+
+ const u16 slot = next_free_slot;
+ if (slot >= table_size) {
+ LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
+ return ResultHandleTableFull;
+ }
+ next_free_slot = generations[slot];
+
+ const u16 generation = next_generation++;
+
+ // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
+ // Horizon OS uses zero to represent an invalid handle, so skip to 1.
+ if (next_generation >= (1 << 15)) {
+ next_generation = 1;
+ }
+
+ generations[slot] = generation;
+ objects_new[slot] = obj;
+ obj->Open();
+
+ *out_handle = generation | (slot << 15);
+
+ return RESULT_SUCCESS;
+}
+
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
std::shared_ptr<Object> object = GetGeneric(handle);
if (object == nullptr) {
@@ -81,30 +108,36 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
return Create(std::move(object));
}
-ResultCode HandleTable::Close(Handle handle) {
+bool HandleTable::Remove(Handle handle) {
if (!IsValid(handle)) {
LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle);
- return ResultInvalidHandle;
+ return {};
}
const u16 slot = GetSlot(handle);
- if (objects[slot].use_count() == 1) {
- objects[slot]->Finalize();
+ if (objects[slot]) {
+ objects[slot]->Close();
+ }
+
+ if (objects_new[slot]) {
+ objects_new[slot]->Close();
}
objects[slot] = nullptr;
+ objects_new[slot] = nullptr;
generations[slot] = next_free_slot;
next_free_slot = slot;
- return RESULT_SUCCESS;
+
+ return true;
}
bool HandleTable::IsValid(Handle handle) const {
const std::size_t slot = GetSlot(handle);
const u16 generation = GetGeneration(handle);
-
- return slot < table_size && objects[slot] != nullptr && generations[slot] == generation;
+ const bool is_object_valid = (objects[slot] != nullptr) || (objects_new[slot] != nullptr);
+ return slot < table_size && is_object_valid && generations[slot] == generation;
}
std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
@@ -124,6 +157,7 @@ void HandleTable::Clear() {
for (u16 i = 0; i < table_size; ++i) {
generations[i] = static_cast<u16>(i + 1);
objects[i] = nullptr;
+ objects_new[i] = nullptr;
}
next_free_slot = 0;
}