| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- // Copyright 2014 Citra Emulator Project / PPSSPP Project
- // Licensed under GPLv2
- // Refer to the license.txt file included.
- #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;
- ObjectPool::ObjectPool() {
- next_id = INITIAL_NEXT_ID;
- }
- 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;
- }
- }
- ERROR_LOG(HLE, "Unable to allocate kernel object, too many objects slots in use.");
- return 0;
- }
- bool ObjectPool::IsValid(Handle handle) {
- int index = handle - HANDLE_OFFSET;
- if (index < 0)
- return false;
- if (index >= MAX_COUNT)
- return false;
- return occupied[index];
- }
- 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;
- }
- pool.fill(nullptr);
- next_id = INITIAL_NEXT_ID;
- }
- Object* &ObjectPool::operator [](Handle handle)
- {
- _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ");
- return pool[handle - HANDLE_OFFSET];
- }
- 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());
- }
- }
- }
- }
- int ObjectPool::GetCount() {
- int count = 0;
- for (int i = 0; i < MAX_COUNT; i++) {
- if (occupied[i])
- count++;
- }
- return count;
- }
- Object* ObjectPool::CreateByIDType(int type) {
- // Used for save states. This is ugly, but what other way is there?
- switch (type) {
- //case SCE_KERNEL_TMID_Alarm:
- // return __KernelAlarmObject();
- //case SCE_KERNEL_TMID_EventFlag:
- // return __KernelEventFlagObject();
- //case SCE_KERNEL_TMID_Mbox:
- // return __KernelMbxObject();
- //case SCE_KERNEL_TMID_Fpl:
- // return __KernelMemoryFPLObject();
- //case SCE_KERNEL_TMID_Vpl:
- // return __KernelMemoryVPLObject();
- //case PPSSPP_KERNEL_TMID_PMB:
- // return __KernelMemoryPMBObject();
- //case PPSSPP_KERNEL_TMID_Module:
- // return __KernelModuleObject();
- //case SCE_KERNEL_TMID_Mpipe:
- // return __KernelMsgPipeObject();
- //case SCE_KERNEL_TMID_Mutex:
- // return __KernelMutexObject();
- //case SCE_KERNEL_TMID_LwMutex:
- // return __KernelLwMutexObject();
- //case SCE_KERNEL_TMID_Semaphore:
- // return __KernelSemaphoreObject();
- //case SCE_KERNEL_TMID_Callback:
- // return __KernelCallbackObject();
- //case SCE_KERNEL_TMID_Thread:
- // return __KernelThreadObject();
- //case SCE_KERNEL_TMID_VTimer:
- // return __KernelVTimerObject();
- //case SCE_KERNEL_TMID_Tlspl:
- // return __KernelTlsplObject();
- //case PPSSPP_KERNEL_TMID_File:
- // return __KernelFileNodeObject();
- //case PPSSPP_KERNEL_TMID_DirList:
- // return __KernelDirListingObject();
- default:
- ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type);
- return nullptr;
- }
- }
- /// 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
- }
- /**
- * Loads executable stored at specified address
- * @entry_point Entry point in memory of loaded executable
- * @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
- g_main_thread = Kernel::SetupMainThread(0x30);
- return true;
- }
- } // namespace
|