2014-05-10 06:11:18 +04:00
|
|
|
// Copyright 2014 Citra Emulator Project / PPSSPP Project
|
|
|
|
// Licensed under GPLv2
|
2014-11-19 11:49:13 +03:00
|
|
|
// Refer to the license.txt file included.
|
2014-05-10 06:11:18 +04:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2014-08-19 08:20:56 +04:00
|
|
|
#include <array>
|
2014-08-18 07:03:22 +04:00
|
|
|
#include <string>
|
2014-05-21 06:27:46 +04:00
|
|
|
#include "common/common.h"
|
2014-10-23 07:20:01 +04:00
|
|
|
#include "core/hle/result.h"
|
2014-05-10 06:11:18 +04:00
|
|
|
|
2014-05-19 02:12:29 +04:00
|
|
|
typedef u32 Handle;
|
|
|
|
typedef s32 Result;
|
2014-05-10 06:11:18 +04:00
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
namespace Kernel {
|
|
|
|
|
2014-05-27 05:56:23 +04:00
|
|
|
enum KernelHandle {
|
|
|
|
CurrentThread = 0xFFFF8000,
|
|
|
|
CurrentProcess = 0xFFFF8001,
|
|
|
|
};
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
enum class HandleType : u32 {
|
|
|
|
Unknown = 0,
|
|
|
|
Port = 1,
|
|
|
|
Service = 2,
|
|
|
|
Event = 3,
|
|
|
|
Mutex = 4,
|
|
|
|
SharedMemory = 5,
|
|
|
|
Redirection = 6,
|
|
|
|
Thread = 7,
|
|
|
|
Process = 8,
|
2014-07-07 07:15:40 +04:00
|
|
|
AddressArbiter = 9,
|
2014-05-21 02:13:25 +04:00
|
|
|
File = 10,
|
|
|
|
Semaphore = 11,
|
2014-06-26 02:15:35 +04:00
|
|
|
Archive = 12,
|
2014-09-12 02:48:04 +04:00
|
|
|
Directory = 13,
|
2014-05-14 05:57:12 +04:00
|
|
|
};
|
2014-11-19 11:49:13 +03:00
|
|
|
|
2014-05-16 02:26:28 +04:00
|
|
|
enum {
|
2014-05-21 02:13:25 +04:00
|
|
|
DEFAULT_STACK_SIZE = 0x4000,
|
2014-05-16 02:26:28 +04:00
|
|
|
};
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
class ObjectPool;
|
2014-05-10 06:11:18 +04:00
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
class Object : NonCopyable {
|
|
|
|
friend class ObjectPool;
|
2014-05-16 02:26:28 +04:00
|
|
|
u32 handle;
|
2014-05-10 06:11:18 +04:00
|
|
|
public:
|
2014-05-21 02:13:25 +04:00
|
|
|
virtual ~Object() {}
|
2014-05-16 02:26:28 +04:00
|
|
|
Handle GetHandle() const { return handle; }
|
2014-08-18 07:03:22 +04:00
|
|
|
virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
|
|
|
|
virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
|
2014-05-21 02:13:25 +04:00
|
|
|
virtual Kernel::HandleType GetHandleType() const = 0;
|
2014-05-27 06:12:46 +04:00
|
|
|
|
|
|
|
/**
|
2014-10-23 07:20:01 +04:00
|
|
|
* Synchronize kernel object.
|
|
|
|
* @return True if the current thread should wait as a result of the sync
|
2014-05-27 06:12:46 +04:00
|
|
|
*/
|
2014-10-23 07:20:01 +04:00
|
|
|
virtual ResultVal<bool> SyncRequest() {
|
2014-06-06 07:13:28 +04:00
|
|
|
ERROR_LOG(KERNEL, "(UNIMPLEMENTED)");
|
2014-10-23 07:20:01 +04:00
|
|
|
return UnimplementedFunction(ErrorModule::Kernel);
|
2014-06-06 07:13:28 +04:00
|
|
|
}
|
2014-05-27 06:12:46 +04:00
|
|
|
|
2014-05-27 06:17:49 +04:00
|
|
|
/**
|
2014-10-23 07:20:01 +04:00
|
|
|
* Wait for kernel object to synchronize.
|
|
|
|
* @return True if the current thread should wait as a result of the wait
|
2014-05-27 06:17:49 +04:00
|
|
|
*/
|
2014-10-23 07:20:01 +04:00
|
|
|
virtual ResultVal<bool> WaitSynchronization() = 0;
|
2014-05-10 06:11:18 +04:00
|
|
|
};
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
class ObjectPool : NonCopyable {
|
2014-05-10 06:11:18 +04:00
|
|
|
public:
|
2014-05-21 02:13:25 +04:00
|
|
|
ObjectPool();
|
|
|
|
~ObjectPool() {}
|
2014-05-10 06:11:18 +04:00
|
|
|
|
2014-05-16 02:26:28 +04:00
|
|
|
// Allocates a handle within the range and inserts the object into the map.
|
2014-05-21 02:13:25 +04:00
|
|
|
Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF);
|
2014-05-10 06:11:18 +04:00
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
static Object* CreateByIDType(int type);
|
2014-05-10 06:11:18 +04:00
|
|
|
|
|
|
|
template <class T>
|
2014-10-23 07:20:01 +04:00
|
|
|
void Destroy(Handle handle) {
|
|
|
|
if (Get<T>(handle)) {
|
2014-05-14 05:57:12 +04:00
|
|
|
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-05-16 02:26:28 +04:00
|
|
|
bool IsValid(Handle handle);
|
2014-05-10 06:11:18 +04:00
|
|
|
|
|
|
|
template <class T>
|
2014-10-23 07:20:01 +04:00
|
|
|
T* Get(Handle handle) {
|
2014-05-14 05:57:12 +04:00
|
|
|
if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
|
2014-10-23 07:20:01 +04:00
|
|
|
if (handle != 0) {
|
2014-05-14 05:57:12 +04:00
|
|
|
WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
|
2014-05-10 06:11:18 +04:00
|
|
|
}
|
2014-10-23 07:20:01 +04:00
|
|
|
return nullptr;
|
2014-05-10 06:11:18 +04:00
|
|
|
} else {
|
2014-10-23 07:20:01 +04:00
|
|
|
Object* t = pool[handle - HANDLE_OFFSET];
|
|
|
|
if (t->GetHandleType() != T::GetStaticHandleType()) {
|
2014-05-14 05:57:12 +04:00
|
|
|
WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle);
|
2014-10-23 07:20:01 +04:00
|
|
|
return nullptr;
|
2014-05-10 06:11:18 +04:00
|
|
|
}
|
2014-10-23 07:20:01 +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>
|
2014-05-16 02:26:28 +04:00
|
|
|
T *GetFast(Handle handle) {
|
|
|
|
const Handle realHandle = handle - HANDLE_OFFSET;
|
2014-05-14 05:57:12 +04:00
|
|
|
_dbg_assert_(KERNEL, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
|
2014-05-21 02:13:25 +04:00
|
|
|
return static_cast<T*>(pool[realHandle]);
|
2014-05-10 06:11:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, typename ArgT>
|
2014-05-21 02:13:25 +04:00
|
|
|
void Iterate(bool func(T*, ArgT), ArgT arg) {
|
2014-05-10 06:11:18 +04:00
|
|
|
int type = T::GetStaticIDType();
|
2014-05-14 05:57:12 +04:00
|
|
|
for (int i = 0; i < MAX_COUNT; i++)
|
2014-05-10 06:11:18 +04:00
|
|
|
{
|
|
|
|
if (!occupied[i])
|
|
|
|
continue;
|
2014-05-21 02:13:25 +04:00
|
|
|
T* t = static_cast<T*>(pool[i]);
|
2014-05-10 06:11:18 +04:00
|
|
|
if (t->GetIDType() == type) {
|
|
|
|
if (!func(t, arg))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
bool GetIDType(Handle handle, HandleType* type) const {
|
2014-11-19 11:49:13 +03:00
|
|
|
if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
|
2014-05-10 06:11:18 +04:00
|
|
|
!occupied[handle - HANDLE_OFFSET]) {
|
|
|
|
ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
|
|
|
|
return false;
|
|
|
|
}
|
2014-05-21 02:13:25 +04:00
|
|
|
Object* t = pool[handle - HANDLE_OFFSET];
|
|
|
|
*type = t->GetHandleType();
|
2014-05-10 06:11:18 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
Object* &operator [](Handle handle);
|
2014-05-10 06:11:18 +04:00
|
|
|
void List();
|
|
|
|
void Clear();
|
|
|
|
int GetCount();
|
|
|
|
|
|
|
|
private:
|
2014-11-19 11:49:13 +03:00
|
|
|
|
2014-05-10 06:11:18 +04:00
|
|
|
enum {
|
|
|
|
MAX_COUNT = 0x1000,
|
|
|
|
HANDLE_OFFSET = 0x100,
|
|
|
|
INITIAL_NEXT_ID = 0x10,
|
|
|
|
};
|
2014-05-21 02:13:25 +04:00
|
|
|
|
2014-08-19 08:20:56 +04:00
|
|
|
std::array<Object*, MAX_COUNT> pool;
|
|
|
|
std::array<bool, MAX_COUNT> occupied;
|
|
|
|
int next_id;
|
2014-05-10 06:11:18 +04:00
|
|
|
};
|
|
|
|
|
2014-05-21 02:13:25 +04:00
|
|
|
extern ObjectPool g_object_pool;
|
2014-06-02 05:42:50 +04:00
|
|
|
extern Handle g_main_thread;
|
2014-05-21 02:13:25 +04:00
|
|
|
|
2014-06-11 06:43:50 +04:00
|
|
|
/// Initialize the kernel
|
|
|
|
void Init();
|
|
|
|
|
|
|
|
/// Shutdown the kernel
|
|
|
|
void Shutdown();
|
|
|
|
|
2014-05-23 03:06:12 +04:00
|
|
|
/**
|
|
|
|
* 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);
|
2014-05-14 05:57:12 +04:00
|
|
|
|
2014-05-23 03:06:12 +04:00
|
|
|
} // namespace
|