citra/src/core/hle/kernel/kernel.cpp

123 lines
2.9 KiB
C++
Raw Normal View History

2014-05-10 04:11:18 +02:00
// 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"
2014-05-10 04:11:18 +02:00
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/archive.h"
2014-05-10 04:11:18 +02:00
namespace Kernel {
2014-05-10 04:11:18 +02:00
Handle g_main_thread = 0;
ObjectPool g_object_pool;
2014-05-10 04:11:18 +02:00
ObjectPool::ObjectPool() {
2014-05-10 04:11:18 +02:00
next_id = INITIAL_NEXT_ID;
}
Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
2014-05-10 04:11:18 +02:00
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;
2014-05-10 04:11:18 +02:00
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) {
2014-05-10 04:11:18 +02:00
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++) {
2014-05-10 04:11:18 +02:00
//brutally clear everything, no validation
if (occupied[i])
delete pool[i];
occupied[i] = false;
}
pool.fill(nullptr);
2014-05-10 04:11:18 +02:00
next_id = INITIAL_NEXT_ID;
}
Object* &ObjectPool::operator [](Handle handle)
2014-05-10 04:11:18 +02:00
{
_dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ");
return pool[handle - HANDLE_OFFSET];
}
void ObjectPool::List() {
2014-05-10 04:11:18 +02:00
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());
2014-05-10 04:11:18 +02:00
}
}
}
}
int ObjectPool::GetCount() {
2014-05-10 04:11:18 +02:00
int count = 0;
for (int i = 0; i < MAX_COUNT; i++) {
2014-05-10 04:11:18 +02:00
if (occupied[i])
count++;
}
return count;
}
Object* ObjectPool::CreateByIDType(int type) {
ERROR_LOG(COMMON, "Unimplemented: %d.", type);
return nullptr;
2014-05-10 04:11:18 +02:00
}
/// 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