citra-emu
/
citra
Archived
1
0
Fork 0

- created a Kernel namespace

- cleaned up Kernel code a bit (moved stuff into namespace, fixed whitespace issues)
- added handle types for all different CTROS handles
This commit is contained in:
bunnei 2014-05-20 18:13:25 -04:00
parent 0886dc70ed
commit 44336329ed
6 changed files with 87 additions and 75 deletions

View File

@ -12,22 +12,16 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
KernelObjectPool g_kernel_objects; namespace Kernel {
void __KernelInit() { ObjectPool g_object_pool;
__KernelThreadingInit();
}
void __KernelShutdown() { ObjectPool::ObjectPool() {
__KernelThreadingShutdown();
}
KernelObjectPool::KernelObjectPool() {
memset(occupied, 0, sizeof(bool) * MAX_COUNT); memset(occupied, 0, sizeof(bool) * MAX_COUNT);
next_id = INITIAL_NEXT_ID; next_id = INITIAL_NEXT_ID;
} }
Handle KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_top) { Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
if (range_top > MAX_COUNT) { if (range_top > MAX_COUNT) {
range_top = MAX_COUNT; range_top = MAX_COUNT;
} }
@ -46,8 +40,7 @@ Handle KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_t
return 0; return 0;
} }
bool KernelObjectPool::IsValid(Handle handle) bool ObjectPool::IsValid(Handle handle) {
{
int index = handle - HANDLE_OFFSET; int index = handle - HANDLE_OFFSET;
if (index < 0) if (index < 0)
return false; return false;
@ -57,26 +50,24 @@ bool KernelObjectPool::IsValid(Handle handle)
return occupied[index]; return occupied[index];
} }
void KernelObjectPool::Clear() void ObjectPool::Clear() {
{ for (int i = 0; i < MAX_COUNT; i++) {
for (int i = 0; i < MAX_COUNT; i++)
{
//brutally clear everything, no validation //brutally clear everything, no validation
if (occupied[i]) if (occupied[i])
delete pool[i]; delete pool[i];
occupied[i] = false; occupied[i] = false;
} }
memset(pool, 0, sizeof(KernelObject*)*MAX_COUNT); memset(pool, 0, sizeof(Object*)*MAX_COUNT);
next_id = INITIAL_NEXT_ID; next_id = INITIAL_NEXT_ID;
} }
KernelObject *&KernelObjectPool::operator [](Handle handle) Object* &ObjectPool::operator [](Handle handle)
{ {
_dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ");
return pool[handle - HANDLE_OFFSET]; return pool[handle - HANDLE_OFFSET];
} }
void KernelObjectPool::List() { void ObjectPool::List() {
for (int i = 0; i < MAX_COUNT; i++) { for (int i = 0; i < MAX_COUNT; i++) {
if (occupied[i]) { if (occupied[i]) {
if (pool[i]) { if (pool[i]) {
@ -87,18 +78,16 @@ void KernelObjectPool::List() {
} }
} }
int KernelObjectPool::GetCount() int ObjectPool::GetCount() {
{
int count = 0; int count = 0;
for (int i = 0; i < MAX_COUNT; i++) for (int i = 0; i < MAX_COUNT; i++) {
{
if (occupied[i]) if (occupied[i])
count++; count++;
} }
return count; return count;
} }
KernelObject *KernelObjectPool::CreateByIDType(int type) { Object* ObjectPool::CreateByIDType(int type) {
// Used for save states. This is ugly, but what other way is there? // Used for save states. This is ugly, but what other way is there?
switch (type) { switch (type) {
//case SCE_KERNEL_TMID_Alarm: //case SCE_KERNEL_TMID_Alarm:
@ -142,8 +131,18 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) {
} }
} }
void Init() {
__KernelThreadingInit();
}
void Shutdown() {
__KernelThreadingShutdown();
}
} // namespace
bool __KernelLoadExec(u32 entry_point) { bool __KernelLoadExec(u32 entry_point) {
__KernelInit(); Kernel::Init();
Core::g_app_core->SetPC(entry_point); Core::g_app_core->SetPC(entry_point);

View File

@ -9,41 +9,50 @@
typedef u32 Handle; typedef u32 Handle;
typedef s32 Result; typedef s32 Result;
enum KernelIDType { namespace Kernel {
KERNEL_ID_TYPE_THREAD,
KERNEL_ID_TYPE_SEMAPHORE,
KERNEL_ID_TYPE_MUTEX,
KERNEL_ID_TYPE_EVENT,
KERNEL_ID_TYPE_SERVICE,
};
enum class HandleType : u32 {
Unknown = 0,
Port = 1,
Service = 2,
Event = 3,
Mutex = 4,
SharedMemory = 5,
Redirection = 6,
Thread = 7,
Process = 8,
Arbiter = 9,
File = 10,
Semaphore = 11,
};
enum { enum {
KERNEL_MAX_NAME_LENGTH = 0x100, MAX_NAME_LENGTH = 0x100,
KERNEL_DEFAULT_STACK_SIZE = 0x4000, DEFAULT_STACK_SIZE = 0x4000,
}; };
class KernelObjectPool; class ObjectPool;
class KernelObject { class Object : NonCopyable {
friend class KernelObjectPool; friend class ObjectPool;
u32 handle; u32 handle;
public: public:
virtual ~KernelObject() {} virtual ~Object() {}
Handle GetHandle() const { return handle; } Handle GetHandle() const { return handle; }
virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; }
virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; }
virtual KernelIDType GetIDType() const = 0; virtual Kernel::HandleType GetHandleType() const = 0;
}; };
class KernelObjectPool { class ObjectPool : NonCopyable {
public: public:
KernelObjectPool(); ObjectPool();
~KernelObjectPool() {} ~ObjectPool() {}
// Allocates a handle within the range and inserts the object into the map. // Allocates a handle within the range and inserts the object into the map.
Handle Create(KernelObject *obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF);
static KernelObject *CreateByIDType(int type); static Object* CreateByIDType(int type);
template <class T> template <class T>
u32 Destroy(Handle handle) { u32 Destroy(Handle handle) {
@ -71,7 +80,7 @@ public:
// it just acted as a static case and everything worked. This means that we will never // it just acted as a static case and everything worked. This means that we will never
// see the Wrong type object error below, but we'll just have to live with that danger. // see the Wrong type object error below, but we'll just have to live with that danger.
T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]); T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]);
if (t == 0 || t->GetIDType() != T::GetStaticIDType()) { if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) {
WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle);
outError = 0;//T::GetMissingErrorCode(); outError = 0;//T::GetMissingErrorCode();
return 0; return 0;
@ -86,17 +95,17 @@ public:
T *GetFast(Handle handle) { T *GetFast(Handle handle) {
const Handle realHandle = handle - HANDLE_OFFSET; const Handle realHandle = handle - HANDLE_OFFSET;
_dbg_assert_(KERNEL, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); _dbg_assert_(KERNEL, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
return static_cast<T *>(pool[realHandle]); return static_cast<T*>(pool[realHandle]);
} }
template <class T, typename ArgT> template <class T, typename ArgT>
void Iterate(bool func(T *, ArgT), ArgT arg) { void Iterate(bool func(T*, ArgT), ArgT arg) {
int type = T::GetStaticIDType(); int type = T::GetStaticIDType();
for (int i = 0; i < MAX_COUNT; i++) for (int i = 0; i < MAX_COUNT; i++)
{ {
if (!occupied[i]) if (!occupied[i])
continue; continue;
T *t = static_cast<T *>(pool[i]); T* t = static_cast<T*>(pool[i]);
if (t->GetIDType() == type) { if (t->GetIDType() == type) {
if (!func(t, arg)) if (!func(t, arg))
break; break;
@ -104,33 +113,37 @@ public:
} }
} }
bool GetIDType(Handle handle, int *type) const { bool GetIDType(Handle handle, HandleType* type) const {
if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
!occupied[handle - HANDLE_OFFSET]) { !occupied[handle - HANDLE_OFFSET]) {
ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
return false; return false;
} }
KernelObject *t = pool[handle - HANDLE_OFFSET]; Object* t = pool[handle - HANDLE_OFFSET];
*type = t->GetIDType(); *type = t->GetHandleType();
return true; return true;
} }
KernelObject *&operator [](Handle handle); Object* &operator [](Handle handle);
void List(); void List();
void Clear(); void Clear();
int GetCount(); int GetCount();
private: private:
enum { enum {
MAX_COUNT = 0x1000, MAX_COUNT = 0x1000,
HANDLE_OFFSET = 0x100, HANDLE_OFFSET = 0x100,
INITIAL_NEXT_ID = 0x10, INITIAL_NEXT_ID = 0x10,
}; };
KernelObject *pool[MAX_COUNT];
bool occupied[MAX_COUNT]; Object* pool[MAX_COUNT];
int next_id; bool occupied[MAX_COUNT];
int next_id;
}; };
extern KernelObjectPool g_kernel_objects; extern ObjectPool g_object_pool;
} // namespace
bool __KernelLoadExec(u32 entry_point); bool __KernelLoadExec(u32 entry_point);

View File

@ -42,14 +42,14 @@ enum WaitType {
WAITTYPE_SYNCH, WAITTYPE_SYNCH,
}; };
class Thread : public KernelObject { class Thread : public Kernel::Object {
public: public:
const char *GetName() { return name; } const char *GetName() { return name; }
const char *GetTypeName() { return "Thread"; } const char *GetTypeName() { return "Thread"; }
static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; }
KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; }
inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
@ -71,7 +71,7 @@ public:
WaitType wait_type; WaitType wait_type;
char name[KERNEL_MAX_NAME_LENGTH+1]; char name[Kernel::MAX_NAME_LENGTH + 1];
}; };
// Lists all thread ids that aren't deleted/etc. // Lists all thread ids that aren't deleted/etc.
@ -201,7 +201,7 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point,
Thread *t = new Thread; Thread *t = new Thread;
handle = g_kernel_objects.Create(t); handle = Kernel::g_object_pool.Create(t);
g_thread_queue.push_back(handle); g_thread_queue.push_back(handle);
g_thread_ready_queue.prepare(priority); g_thread_ready_queue.prepare(priority);
@ -214,8 +214,8 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point,
t->processor_id = processor_id; t->processor_id = processor_id;
t->wait_type = WAITTYPE_NONE; t->wait_type = WAITTYPE_NONE;
strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH); strncpy(t->name, name, Kernel::MAX_NAME_LENGTH);
t->name[KERNEL_MAX_NAME_LENGTH] = '\0'; t->name[Kernel::MAX_NAME_LENGTH] = '\0';
return t; return t;
} }
@ -296,7 +296,7 @@ Thread *__KernelNextThread() {
if (next < 0) { if (next < 0) {
return NULL; return NULL;
} }
return g_kernel_objects.GetFast<Thread>(next); return Kernel::g_object_pool.GetFast<Thread>(next);
} }
/// Sets up the primary application thread /// Sets up the primary application thread
@ -326,7 +326,7 @@ Handle __KernelSetupMainThread(s32 priority, int stack_size) {
/// Resumes a thread from waiting by marking it as "ready" /// Resumes a thread from waiting by marking it as "ready"
void __KernelResumeThreadFromWait(Handle handle) { void __KernelResumeThreadFromWait(Handle handle) {
u32 error; u32 error;
Thread *t = g_kernel_objects.Get<Thread>(handle, error); Thread *t = Kernel::g_object_pool.Get<Thread>(handle, error);
if (t) { if (t) {
t->status &= ~THREADSTATUS_WAIT; t->status &= ~THREADSTATUS_WAIT;
if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {

View File

@ -23,10 +23,10 @@ enum ThreadProcessorId {
/// Creates a new thread - wrapper for external user /// Creates a new thread - wrapper for external user
Handle __KernelCreateThread(const char *name, u32 entry_point, s32 priority, Handle __KernelCreateThread(const char *name, u32 entry_point, s32 priority,
s32 processor_id, u32 stack_top, int stack_size=KERNEL_DEFAULT_STACK_SIZE); s32 processor_id, u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE);
/// Sets up the primary application thread /// Sets up the primary application thread
Handle __KernelSetupMainThread(s32 priority, int stack_size=KERNEL_DEFAULT_STACK_SIZE); Handle __KernelSetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE);
/// Reschedules to the next available thread (call after current thread is suspended) /// Reschedules to the next available thread (call after current thread is suspended)
void __KernelReschedule(const char *reason); void __KernelReschedule(const char *reason);

View File

@ -34,7 +34,7 @@ Manager::~Manager() {
/// Add a service to the manager (does not create it though) /// Add a service to the manager (does not create it though)
void Manager::AddService(Interface* service) { void Manager::AddService(Interface* service) {
m_port_map[service->GetPortName()] = g_kernel_objects.Create(service); m_port_map[service->GetPortName()] = Kernel::g_object_pool.Create(service);
m_services.push_back(service); m_services.push_back(service);
} }
@ -48,7 +48,7 @@ void Manager::DeleteService(std::string port_name) {
/// Get a Service Interface from its Handle /// Get a Service Interface from its Handle
Interface* Manager::FetchFromHandle(Handle handle) { Interface* Manager::FetchFromHandle(Handle handle) {
return g_kernel_objects.GetFast<Interface>(handle); return Kernel::g_object_pool.GetFast<Interface>(handle);
} }
/// Get a Service Interface from its port /// Get a Service Interface from its port

View File

@ -36,15 +36,15 @@ inline static u32* GetCommandBuffer(const int offset=0) {
class Manager; class Manager;
/// Interface to a CTROS service /// Interface to a CTROS service
class Interface : public KernelObject { class Interface : public Kernel::Object {
friend class Manager; friend class Manager;
public: public:
const char *GetName() { return GetPortName(); } const char *GetName() { return GetPortName(); }
const char *GetTypeName() { return GetPortName(); } const char *GetTypeName() { return GetPortName(); }
static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; }
KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; }
typedef void (*Function)(Interface*); typedef void (*Function)(Interface*);
@ -63,8 +63,8 @@ public:
} }
/// Allocates a new handle for the service /// Allocates a new handle for the service
Handle CreateHandle(KernelObject *obj) { Handle CreateHandle(Kernel::Object *obj) {
Handle handle = g_kernel_objects.Create(obj); Handle handle = Kernel::g_object_pool.Create(obj);
m_handles.push_back(handle); m_handles.push_back(handle);
return handle; return handle;
} }
@ -72,7 +72,7 @@ public:
/// Frees a handle from the service /// Frees a handle from the service
template <class T> template <class T>
void DeleteHandle(const Handle handle) { void DeleteHandle(const Handle handle) {
g_kernel_objects.Destroy<T>(handle); g_object_pool.Destroy<T>(handle);
m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
} }