yuzu/src/core/hle/kernel/kernel.h

186 lines
5.0 KiB
C
Raw Normal View History

2014-05-10 06:11:18 +04:00
// Copyright 2014 Citra Emulator Project / PPSSPP Project
2014-12-17 08:38:14 +03:00
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
2014-05-10 06:11:18 +04:00
#pragma once
#include <array>
#include <string>
#include "common/common.h"
#include "core/hle/result.h"
2014-05-10 06:11:18 +04:00
typedef u32 Handle;
typedef s32 Result;
2014-05-10 06:11:18 +04:00
namespace Kernel {
// From kernel.h. Declarations duplicated here to avoid a circular header dependency.
class Thread;
Thread* GetCurrentThread();
enum KernelHandle {
CurrentThread = 0xFFFF8000,
CurrentProcess = 0xFFFF8001,
};
enum class HandleType : u32 {
Unknown = 0,
Port = 1,
Session = 2,
Event = 3,
Mutex = 4,
SharedMemory = 5,
Redirection = 6,
Thread = 7,
Process = 8,
AddressArbiter = 9,
Semaphore = 10,
};
enum {
DEFAULT_STACK_SIZE = 0x4000,
};
2014-12-14 02:16:13 +03:00
class HandleTable;
2014-05-10 06:11:18 +04:00
class Object : NonCopyable {
2014-12-14 02:16:13 +03:00
friend class HandleTable;
u32 handle;
2014-05-10 06:11:18 +04:00
public:
virtual ~Object() {}
Handle GetHandle() const { return handle; }
virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
virtual Kernel::HandleType GetHandleType() const = 0;
/**
* Wait for kernel object to synchronize.
* @return True if the current thread should wait as a result of the wait
*/
virtual ResultVal<bool> WaitSynchronization() {
LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
return UnimplementedFunction(ErrorModule::Kernel);
}
2014-05-10 06:11:18 +04:00
};
2014-12-14 02:16:13 +03:00
class HandleTable : NonCopyable {
2014-05-10 06:11:18 +04:00
public:
2014-12-14 02:16:13 +03:00
HandleTable();
~HandleTable() {}
2014-05-10 06:11:18 +04:00
// Allocates a handle within the range and inserts the object into the map.
Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF);
2014-05-10 06:11:18 +04:00
static Object* CreateByIDType(int type);
2014-05-10 06:11:18 +04:00
template <class T>
void Destroy(Handle handle) {
if (Get<T>(handle)) {
occupied[handle - HANDLE_OFFSET] = false;
delete pool[handle - HANDLE_OFFSET];
2014-05-10 06:11:18 +04:00
}
2014-11-18 16:27:16 +03:00
}
2014-05-10 06:11:18 +04:00
2014-12-04 03:48:34 +03:00
bool IsValid(Handle handle) const;
2014-05-10 06:11:18 +04:00
template <class T>
T* Get(Handle handle) {
if (handle == CurrentThread) {
return reinterpret_cast<T*>(GetCurrentThread());
}
if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
if (handle != 0) {
2014-12-13 18:15:58 +03:00
LOG_ERROR(Kernel, "Bad object handle %08x", handle);
2014-05-10 06:11:18 +04:00
}
return nullptr;
2014-05-10 06:11:18 +04:00
} else {
Object* t = pool[handle - HANDLE_OFFSET];
if (t->GetHandleType() != T::HANDLE_TYPE) {
2014-12-13 18:15:58 +03:00
LOG_ERROR(Kernel, "Wrong object type for %08x", handle);
return nullptr;
2014-05-10 06:11:18 +04:00
}
return static_cast<T*>(t);
2014-05-10 06:11:18 +04:00
}
}
// ONLY use this when you know the handle is valid.
template <class T>
T *GetFast(Handle handle) {
if (handle == CurrentThread) {
return reinterpret_cast<T*>(GetCurrentThread());
}
const Handle realHandle = handle - HANDLE_OFFSET;
_dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
return static_cast<T*>(pool[realHandle]);
2014-05-10 06:11:18 +04:00
}
template <class T, typename ArgT>
void Iterate(bool func(T*, ArgT), ArgT arg) {
2014-05-10 06:11:18 +04:00
int type = T::GetStaticIDType();
for (int i = 0; i < MAX_COUNT; i++)
2014-05-10 06:11:18 +04:00
{
if (!occupied[i])
continue;
T* t = static_cast<T*>(pool[i]);
2014-05-10 06:11:18 +04:00
if (t->GetIDType() == type) {
if (!func(t, arg))
break;
}
}
}
bool GetIDType(Handle handle, HandleType* type) const {
if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
!occupied[handle - HANDLE_OFFSET]) {
2014-12-13 18:15:58 +03:00
LOG_ERROR(Kernel, "Bad object handle %08X", handle);
2014-05-10 06:11:18 +04:00
return false;
}
Object* t = pool[handle - HANDLE_OFFSET];
*type = t->GetHandleType();
2014-05-10 06:11:18 +04:00
return true;
}
Object* &operator [](Handle handle);
2014-05-10 06:11:18 +04:00
void List();
void Clear();
2014-12-04 03:48:34 +03:00
int GetCount() const;
2014-05-10 06:11:18 +04:00
private:
2014-05-10 06:11:18 +04:00
enum {
MAX_COUNT = 0x1000,
HANDLE_OFFSET = 0x100,
INITIAL_NEXT_ID = 0x10,
};
std::array<Object*, MAX_COUNT> pool;
std::array<bool, MAX_COUNT> occupied;
int next_id;
2014-05-10 06:11:18 +04:00
};
2014-12-14 02:16:13 +03:00
extern HandleTable g_handle_table;
extern Handle g_main_thread;
/// The ID code of the currently running game
/// TODO(Subv): This variable should not be here,
/// we need a way to store information about the currently loaded application
/// for later query during runtime, maybe using the LDR service?
extern u64 g_program_id;
/// Initialize the kernel
void Init();
/// Shutdown the kernel
void Shutdown();
/**
* 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);
} // namespace