mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	- 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:
		
							parent
							
								
									0886dc70ed
								
							
						
					
					
						commit
						44336329ed
					
				
					 6 changed files with 87 additions and 75 deletions
				
			
		|  | @ -12,22 +12,16 @@ | |||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| KernelObjectPool g_kernel_objects; | ||||
| namespace Kernel { | ||||
| 
 | ||||
| void __KernelInit() { | ||||
|     __KernelThreadingInit(); | ||||
| } | ||||
| ObjectPool g_object_pool; | ||||
| 
 | ||||
| void __KernelShutdown() { | ||||
|     __KernelThreadingShutdown(); | ||||
| } | ||||
| 
 | ||||
| KernelObjectPool::KernelObjectPool() { | ||||
| ObjectPool::ObjectPool() { | ||||
|     memset(occupied, 0, sizeof(bool) * MAX_COUNT); | ||||
|     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) { | ||||
|         range_top = MAX_COUNT; | ||||
|     } | ||||
|  | @ -46,8 +40,7 @@ Handle KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_t | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| bool KernelObjectPool::IsValid(Handle handle) | ||||
| { | ||||
| bool ObjectPool::IsValid(Handle handle) { | ||||
|     int index = handle - HANDLE_OFFSET; | ||||
|     if (index < 0) | ||||
|         return false; | ||||
|  | @ -57,26 +50,24 @@ bool KernelObjectPool::IsValid(Handle handle) | |||
|     return occupied[index]; | ||||
| } | ||||
| 
 | ||||
| void KernelObjectPool::Clear() | ||||
| { | ||||
|     for (int i = 0; i < MAX_COUNT; i++) | ||||
|     { | ||||
| 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; | ||||
|     } | ||||
|     memset(pool, 0, sizeof(KernelObject*)*MAX_COUNT); | ||||
|     memset(pool, 0, sizeof(Object*)*MAX_COUNT); | ||||
|     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"); | ||||
|     return pool[handle - HANDLE_OFFSET]; | ||||
| } | ||||
| 
 | ||||
| void KernelObjectPool::List() { | ||||
| void ObjectPool::List() { | ||||
|     for (int i = 0; i < MAX_COUNT; i++) { | ||||
|         if (occupied[i]) { | ||||
|             if (pool[i]) { | ||||
|  | @ -87,18 +78,16 @@ void KernelObjectPool::List() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| int KernelObjectPool::GetCount() | ||||
| { | ||||
| int ObjectPool::GetCount() { | ||||
|     int count = 0; | ||||
|     for (int i = 0; i < MAX_COUNT; i++) | ||||
|     { | ||||
|     for (int i = 0; i < MAX_COUNT; i++) { | ||||
|         if (occupied[i]) | ||||
|             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?
 | ||||
|     switch (type) { | ||||
|     //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) { | ||||
|     __KernelInit(); | ||||
|     Kernel::Init(); | ||||
|      | ||||
|     Core::g_app_core->SetPC(entry_point); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,41 +9,50 @@ | |||
| typedef u32 Handle; | ||||
| typedef s32 Result; | ||||
| 
 | ||||
| enum KernelIDType { | ||||
|     KERNEL_ID_TYPE_THREAD, | ||||
|     KERNEL_ID_TYPE_SEMAPHORE, | ||||
|     KERNEL_ID_TYPE_MUTEX, | ||||
|     KERNEL_ID_TYPE_EVENT, | ||||
|     KERNEL_ID_TYPE_SERVICE, | ||||
| namespace Kernel { | ||||
| 
 | ||||
| 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 { | ||||
|     KERNEL_MAX_NAME_LENGTH      = 0x100, | ||||
|     KERNEL_DEFAULT_STACK_SIZE   = 0x4000, | ||||
|     MAX_NAME_LENGTH     = 0x100, | ||||
|     DEFAULT_STACK_SIZE  = 0x4000, | ||||
| }; | ||||
| 
 | ||||
| class KernelObjectPool; | ||||
| class ObjectPool; | ||||
| 
 | ||||
| class KernelObject { | ||||
|     friend class KernelObjectPool; | ||||
| class Object : NonCopyable { | ||||
|     friend class ObjectPool; | ||||
|     u32 handle; | ||||
| public: | ||||
|     virtual ~KernelObject() {} | ||||
|     virtual ~Object() {} | ||||
|     Handle GetHandle() const { return handle; } | ||||
|     virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } | ||||
|     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: | ||||
|     KernelObjectPool(); | ||||
|     ~KernelObjectPool() {} | ||||
|     ObjectPool(); | ||||
|     ~ObjectPool() {} | ||||
| 
 | ||||
|     // 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> | ||||
|     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
 | ||||
|             // 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]); | ||||
|             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); | ||||
|                 outError = 0;//T::GetMissingErrorCode();
 | ||||
|                 return 0; | ||||
|  | @ -86,17 +95,17 @@ public: | |||
|     T *GetFast(Handle handle) { | ||||
|         const Handle realHandle = handle - HANDLE_OFFSET; | ||||
|         _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> | ||||
|     void Iterate(bool func(T *, ArgT), ArgT arg) { | ||||
|     void Iterate(bool func(T*, ArgT), ArgT arg) { | ||||
|         int type = T::GetStaticIDType(); | ||||
|         for (int i = 0; i < MAX_COUNT; i++) | ||||
|         { | ||||
|             if (!occupied[i]) | ||||
|                 continue; | ||||
|             T *t = static_cast<T *>(pool[i]); | ||||
|             T* t = static_cast<T*>(pool[i]); | ||||
|             if (t->GetIDType() == type) { | ||||
|                 if (!func(t, arg)) | ||||
|                     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) ||  | ||||
|             !occupied[handle - HANDLE_OFFSET]) { | ||||
|             ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); | ||||
|             return false; | ||||
|         } | ||||
|         KernelObject *t = pool[handle - HANDLE_OFFSET]; | ||||
|         *type = t->GetIDType(); | ||||
|         Object* t = pool[handle - HANDLE_OFFSET]; | ||||
|         *type = t->GetHandleType(); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     KernelObject *&operator [](Handle handle); | ||||
|     Object* &operator [](Handle handle); | ||||
|     void List(); | ||||
|     void Clear(); | ||||
|     int GetCount(); | ||||
| 
 | ||||
| private: | ||||
|      | ||||
|     enum { | ||||
|         MAX_COUNT       = 0x1000, | ||||
|         HANDLE_OFFSET   = 0x100, | ||||
|         INITIAL_NEXT_ID = 0x10, | ||||
|     }; | ||||
|     KernelObject *pool[MAX_COUNT]; | ||||
|     bool occupied[MAX_COUNT]; | ||||
|     int next_id; | ||||
| 
 | ||||
|     Object* pool[MAX_COUNT]; | ||||
|     bool    occupied[MAX_COUNT]; | ||||
|     int     next_id; | ||||
| }; | ||||
| 
 | ||||
| extern KernelObjectPool g_kernel_objects; | ||||
| extern ObjectPool g_object_pool; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| bool __KernelLoadExec(u32 entry_point); | ||||
|  |  | |||
|  | @ -42,14 +42,14 @@ enum WaitType { | |||
|     WAITTYPE_SYNCH, | ||||
| }; | ||||
| 
 | ||||
| class Thread : public KernelObject { | ||||
| class Thread : public Kernel::Object { | ||||
| public: | ||||
| 
 | ||||
|     const char *GetName() { return name; } | ||||
|     const char *GetTypeName() { return "Thread"; } | ||||
| 
 | ||||
|     static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } | ||||
|     KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } | ||||
|     static Kernel::HandleType GetStaticHandleType() {  return Kernel::HandleType::Thread; } | ||||
|     Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; } | ||||
| 
 | ||||
|     inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } | ||||
|     inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } | ||||
|  | @ -71,7 +71,7 @@ public: | |||
| 
 | ||||
|     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.
 | ||||
|  | @ -201,7 +201,7 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, | |||
| 
 | ||||
|     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_ready_queue.prepare(priority); | ||||
|  | @ -214,8 +214,8 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, | |||
|     t->processor_id = processor_id; | ||||
|     t->wait_type = WAITTYPE_NONE; | ||||
|      | ||||
|     strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH); | ||||
|     t->name[KERNEL_MAX_NAME_LENGTH] = '\0'; | ||||
|     strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); | ||||
|     t->name[Kernel::MAX_NAME_LENGTH] = '\0'; | ||||
|      | ||||
|     return t; | ||||
| } | ||||
|  | @ -296,7 +296,7 @@ Thread *__KernelNextThread() { | |||
|     if (next < 0) { | ||||
|         return NULL; | ||||
|     } | ||||
|     return g_kernel_objects.GetFast<Thread>(next); | ||||
|     return Kernel::g_object_pool.GetFast<Thread>(next); | ||||
| } | ||||
| 
 | ||||
| /// 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"
 | ||||
| void __KernelResumeThreadFromWait(Handle handle) { | ||||
|     u32 error; | ||||
|     Thread *t = g_kernel_objects.Get<Thread>(handle, error); | ||||
|     Thread *t = Kernel::g_object_pool.Get<Thread>(handle, error); | ||||
|     if (t) { | ||||
|         t->status &= ~THREADSTATUS_WAIT; | ||||
|         if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | ||||
|  |  | |||
|  | @ -23,10 +23,10 @@ enum ThreadProcessorId { | |||
| 
 | ||||
| /// Creates a new thread - wrapper for external user
 | ||||
| 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
 | ||||
| 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)
 | ||||
| void __KernelReschedule(const char *reason); | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ Manager::~Manager() { | |||
| 
 | ||||
| /// Add a service to the manager (does not create it though)
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
|  | @ -48,7 +48,7 @@ void Manager::DeleteService(std::string port_name) { | |||
| 
 | ||||
| /// Get a Service Interface from its 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
 | ||||
|  |  | |||
|  | @ -36,15 +36,15 @@ inline static u32* GetCommandBuffer(const int offset=0) { | |||
| class Manager; | ||||
| 
 | ||||
| /// Interface to a CTROS service
 | ||||
| class Interface  : public KernelObject { | ||||
| class Interface  : public Kernel::Object { | ||||
|     friend class Manager; | ||||
| public: | ||||
|      | ||||
|     const char *GetName() { return GetPortName(); } | ||||
|     const char *GetTypeName() { return GetPortName(); } | ||||
| 
 | ||||
|     static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } | ||||
|     KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } | ||||
|     static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } | ||||
|     Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } | ||||
| 
 | ||||
|     typedef void (*Function)(Interface*); | ||||
| 
 | ||||
|  | @ -63,8 +63,8 @@ public: | |||
|     } | ||||
| 
 | ||||
|     /// Allocates a new handle for the service
 | ||||
|     Handle CreateHandle(KernelObject *obj) { | ||||
|         Handle handle = g_kernel_objects.Create(obj); | ||||
|     Handle CreateHandle(Kernel::Object *obj) { | ||||
|         Handle handle = Kernel::g_object_pool.Create(obj); | ||||
|         m_handles.push_back(handle); | ||||
|         return handle; | ||||
|     } | ||||
|  | @ -72,7 +72,7 @@ public: | |||
|     /// Frees a handle from the service
 | ||||
|     template <class T> | ||||
|     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()); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue