diff options
author | darkf <lw9k123@gmail.com> | 2014-12-30 04:47:41 +0100 |
---|---|---|
committer | darkf <lw9k123@gmail.com> | 2014-12-30 04:47:41 +0100 |
commit | 8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch) | |
tree | f1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/hle/kernel/kernel.cpp | |
parent | Add comment regarding __WIN32__ in SkyEye code (diff) | |
parent | Merge pull request #367 from bunnei/usat_ssat (diff) | |
download | yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.bz2 yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.lz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.zst yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip |
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 139 |
1 files changed, 74 insertions, 65 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 018000abd..e59ed1b57 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -1,106 +1,117 @@ -// Copyright 2014 Citra Emulator Project / PPSSPP Project -// Licensed under GPLv2 +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> + #include "common/common.h" #include "core/core.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" -#include "core/hle/kernel/archive.h" namespace Kernel { Handle g_main_thread = 0; -ObjectPool g_object_pool; +HandleTable g_handle_table; +u64 g_program_id = 0; -ObjectPool::ObjectPool() { - next_id = INITIAL_NEXT_ID; +HandleTable::HandleTable() { + next_generation = 1; + Clear(); } -Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) { - if (range_top > MAX_COUNT) { - range_top = MAX_COUNT; - } - if (next_id >= range_bottom && next_id < range_top) { - range_bottom = next_id++; - } - for (int i = range_bottom; i < range_top; i++) { - if (!occupied[i]) { - occupied[i] = true; - pool[i] = obj; - pool[i]->handle = i + HANDLE_OFFSET; - return i + HANDLE_OFFSET; - } +ResultVal<Handle> HandleTable::Create(Object* obj) { + _dbg_assert_(Kernel, 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; } - ERROR_LOG(HLE, "Unable to allocate kernel object, too many objects slots in use."); - return 0; -} + next_free_slot = generations[slot]; + + u16 generation = next_generation++; -bool ObjectPool::IsValid(Handle handle) { - int index = handle - HANDLE_OFFSET; - if (index < 0) - return false; - if (index >= MAX_COUNT) - return false; + // 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; - return occupied[index]; + generations[slot] = generation; + intrusive_ptr_add_ref(obj); + objects[slot] = obj; + + Handle handle = generation | (slot << 15); + obj->handle = handle; + return MakeResult<Handle>(handle); } -void ObjectPool::Clear() { - for (int i = 0; i < MAX_COUNT; i++) { - //brutally clear everything, no validation - if (occupied[i]) - delete pool[i]; - occupied[i] = false; +ResultVal<Handle> HandleTable::Duplicate(Handle handle) { + Object* object = GetGeneric(handle); + if (object == nullptr) { + LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); + return ERR_INVALID_HANDLE; } - pool.fill(nullptr); - next_id = INITIAL_NEXT_ID; + return Create(object); +} + +ResultCode HandleTable::Close(Handle handle) { + if (!IsValid(handle)) + return ERR_INVALID_HANDLE; + + size_t slot = GetSlot(handle); + u16 generation = GetGeneration(handle); + + intrusive_ptr_release(objects[slot]); + objects[slot] = nullptr; + + generations[generation] = next_free_slot; + next_free_slot = slot; + return RESULT_SUCCESS; } -Object* &ObjectPool::operator [](Handle handle) -{ - _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); - return pool[handle - HANDLE_OFFSET]; +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; } -void ObjectPool::List() { - for (int i = 0; i < MAX_COUNT; i++) { - if (occupied[i]) { - if (pool[i]) { - INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), - pool[i]->GetName().c_str()); - } - } +Object* HandleTable::GetGeneric(Handle handle) const { + if (handle == CurrentThread) { + // TODO(yuriks) Directly return the pointer once this is possible. + handle = GetCurrentThreadHandle(); + } else if (handle == CurrentProcess) { + LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess); + return nullptr; } -} -int ObjectPool::GetCount() { - int count = 0; - for (int i = 0; i < MAX_COUNT; i++) { - if (occupied[i]) - count++; + if (!IsValid(handle)) { + return nullptr; } - return count; + return objects[GetSlot(handle)]; } -Object* ObjectPool::CreateByIDType(int type) { - ERROR_LOG(COMMON, "Unimplemented: %d.", type); - return nullptr; +void HandleTable::Clear() { + for (size_t i = 0; i < MAX_COUNT; ++i) { + generations[i] = i + 1; + if (objects[i] != nullptr) + intrusive_ptr_release(objects[i]); + objects[i] = nullptr; + } + next_free_slot = 0; } /// Initialize the kernel void Init() { Kernel::ThreadingInit(); - Kernel::ArchiveInit(); } /// Shutdown the kernel void Shutdown() { Kernel::ThreadingShutdown(); - Kernel::ArchiveShutdown(); - g_object_pool.Clear(); // Free all kernel objects + g_handle_table.Clear(); // Free all kernel objects } /** @@ -109,8 +120,6 @@ void Shutdown() { * @return True on success, otherwise false */ bool LoadExec(u32 entry_point) { - Init(); - Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far |