mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Kernel: Start using boost::intrusive_ptr for lifetime management
This commit is contained in:
		
							parent
							
								
									d751de7341
								
							
						
					
					
						commit
						8ad41775cc
					
				
					 13 changed files with 96 additions and 91 deletions
				
			
		|  | @ -30,7 +30,7 @@ public: | |||
| 
 | ||||
| /// Arbitrate an address
 | ||||
| ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { | ||||
|     Object* object = Kernel::g_handle_table.GetGeneric(handle); | ||||
|     Object* object = Kernel::g_handle_table.GetGeneric(handle).get(); | ||||
|     if (object == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ public: | |||
|  * @return Result of operation, 0 on success, otherwise error code | ||||
|  */ | ||||
| ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { | ||||
|     Event* evt = g_handle_table.Get<Event>(handle); | ||||
|     Event* evt = g_handle_table.Get<Event>(handle).get(); | ||||
|     if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     evt->permanent_locked = permanent_locked; | ||||
|  | @ -67,7 +67,7 @@ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { | |||
|  * @return Result of operation, 0 on success, otherwise error code | ||||
|  */ | ||||
| ResultCode SetEventLocked(const Handle handle, const bool locked) { | ||||
|     Event* evt = g_handle_table.Get<Event>(handle); | ||||
|     Event* evt = g_handle_table.Get<Event>(handle).get(); | ||||
|     if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     if (!evt->permanent_locked) { | ||||
|  | @ -82,13 +82,13 @@ ResultCode SetEventLocked(const Handle handle, const bool locked) { | |||
|  * @return Result of operation, 0 on success, otherwise error code | ||||
|  */ | ||||
| ResultCode SignalEvent(const Handle handle) { | ||||
|     Event* evt = g_handle_table.Get<Event>(handle); | ||||
|     Event* evt = g_handle_table.Get<Event>(handle).get(); | ||||
|     if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     // Resume threads waiting for event to signal
 | ||||
|     bool event_caught = false; | ||||
|     for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { | ||||
|         Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]); | ||||
|         Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get(); | ||||
|         if (thread != nullptr) | ||||
|             thread->ResumeFromWait(); | ||||
| 
 | ||||
|  | @ -112,7 +112,7 @@ ResultCode SignalEvent(const Handle handle) { | |||
|  * @return Result of operation, 0 on success, otherwise error code | ||||
|  */ | ||||
| ResultCode ClearEvent(Handle handle) { | ||||
|     Event* evt = g_handle_table.Get<Event>(handle); | ||||
|     Event* evt = g_handle_table.Get<Event>(handle).get(); | ||||
|     if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     if (!evt->permanent_locked) { | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| Thread* g_main_thread = nullptr; | ||||
| SharedPtr<Thread> g_main_thread = nullptr; | ||||
| HandleTable g_handle_table; | ||||
| u64 g_program_id = 0; | ||||
| 
 | ||||
|  | @ -23,7 +23,7 @@ HandleTable::HandleTable() { | |||
|     Clear(); | ||||
| } | ||||
| 
 | ||||
| ResultVal<Handle> HandleTable::Create(Object* obj) { | ||||
| ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | ||||
|     _dbg_assert_(Kernel, obj != nullptr); | ||||
| 
 | ||||
|     u16 slot = next_free_slot; | ||||
|  | @ -39,23 +39,23 @@ ResultVal<Handle> HandleTable::Create(Object* obj) { | |||
|     // CTR-OS doesn't use generation 0, so skip straight to 1.
 | ||||
|     if (next_generation >= (1 << 15)) next_generation = 1; | ||||
| 
 | ||||
|     generations[slot] = generation; | ||||
|     intrusive_ptr_add_ref(obj); | ||||
|     objects[slot] = obj; | ||||
| 
 | ||||
|     Handle handle = generation | (slot << 15); | ||||
|     if (obj->handle == INVALID_HANDLE) | ||||
|         obj->handle = handle; | ||||
| 
 | ||||
|     generations[slot] = generation; | ||||
|     objects[slot] = std::move(obj); | ||||
| 
 | ||||
|     return MakeResult<Handle>(handle); | ||||
| } | ||||
| 
 | ||||
| ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | ||||
|     Object* object = GetGeneric(handle); | ||||
|     SharedPtr<Object> object = GetGeneric(handle); | ||||
|     if (object == nullptr) { | ||||
|         LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); | ||||
|         return ERR_INVALID_HANDLE; | ||||
|     } | ||||
|     return Create(object); | ||||
|     return Create(std::move(object)); | ||||
| } | ||||
| 
 | ||||
| ResultCode HandleTable::Close(Handle handle) { | ||||
|  | @ -65,7 +65,6 @@ ResultCode HandleTable::Close(Handle handle) { | |||
|     size_t slot = GetSlot(handle); | ||||
|     u16 generation = GetGeneration(handle); | ||||
| 
 | ||||
|     intrusive_ptr_release(objects[slot]); | ||||
|     objects[slot] = nullptr; | ||||
| 
 | ||||
|     generations[generation] = next_free_slot; | ||||
|  | @ -80,7 +79,7 @@ bool HandleTable::IsValid(Handle handle) const { | |||
|     return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; | ||||
| } | ||||
| 
 | ||||
| Object* HandleTable::GetGeneric(Handle handle) const { | ||||
| SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { | ||||
|     if (handle == CurrentThread) { | ||||
|         return GetCurrentThread(); | ||||
|     } else if (handle == CurrentProcess) { | ||||
|  | @ -97,8 +96,6 @@ Object* HandleTable::GetGeneric(Handle handle) const { | |||
| void HandleTable::Clear() { | ||||
|     for (size_t i = 0; i < MAX_COUNT; ++i) { | ||||
|         generations[i] = i + 1; | ||||
|         if (objects[i] != nullptr) | ||||
|             intrusive_ptr_release(objects[i]); | ||||
|         objects[i] = nullptr; | ||||
|     } | ||||
|     next_free_slot = 0; | ||||
|  | @ -126,7 +123,7 @@ bool LoadExec(u32 entry_point) { | |||
|     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); | ||||
|     g_main_thread = Kernel::SetupMainThread(0x30, Kernel::DEFAULT_STACK_SIZE); | ||||
|     // Setup the idle thread
 | ||||
|     Kernel::SetupIdleThread(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <boost/intrusive_ptr.hpp> | ||||
| 
 | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include "common/common.h" | ||||
|  | @ -76,7 +78,7 @@ private: | |||
|     unsigned int ref_count = 0; | ||||
| }; | ||||
| 
 | ||||
| // Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting
 | ||||
| // Special functions used by boost::instrusive_ptr to do automatic ref-counting
 | ||||
| inline void intrusive_ptr_add_ref(Object* object) { | ||||
|     ++object->ref_count; | ||||
| } | ||||
|  | @ -87,6 +89,9 @@ inline void intrusive_ptr_release(Object* object) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| using SharedPtr = boost::intrusive_ptr<T>; | ||||
| 
 | ||||
| /**
 | ||||
|  * This class allows the creation of Handles, which are references to objects that can be tested | ||||
|  * for validity and looked up. Here they are used to pass references to kernel objects to/from the | ||||
|  | @ -119,7 +124,7 @@ public: | |||
|      * @return The created Handle or one of the following errors: | ||||
|      *           - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. | ||||
|      */ | ||||
|     ResultVal<Handle> Create(Object* obj); | ||||
|     ResultVal<Handle> Create(SharedPtr<Object> obj); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Returns a new handle that points to the same object as the passed in handle. | ||||
|  | @ -143,7 +148,7 @@ public: | |||
|      * Looks up a handle. | ||||
|      * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid. | ||||
|      */ | ||||
|     Object* GetGeneric(Handle handle) const; | ||||
|     SharedPtr<Object> GetGeneric(Handle handle) const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Looks up a handle while verifying its type. | ||||
|  | @ -151,10 +156,10 @@ public: | |||
|      *          type differs from the handle type `T::HANDLE_TYPE`. | ||||
|      */ | ||||
|     template <class T> | ||||
|     T* Get(Handle handle) const { | ||||
|         Object* object = GetGeneric(handle); | ||||
|     SharedPtr<T> Get(Handle handle) const { | ||||
|         SharedPtr<Object> object = GetGeneric(handle); | ||||
|         if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) { | ||||
|             return static_cast<T*>(object); | ||||
|             return boost::static_pointer_cast<T>(std::move(object)); | ||||
|         } | ||||
|         return nullptr; | ||||
|     } | ||||
|  | @ -173,7 +178,7 @@ private: | |||
|     static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } | ||||
| 
 | ||||
|     /// Stores the Object referenced by the handle or null if the slot is empty.
 | ||||
|     std::array<Object*, MAX_COUNT> objects; | ||||
|     std::array<SharedPtr<Object>, MAX_COUNT> objects; | ||||
| 
 | ||||
|     /**
 | ||||
|      * The value of `next_generation` when the handle was created, used to check for validity. For | ||||
|  | @ -192,7 +197,7 @@ private: | |||
| }; | ||||
| 
 | ||||
| extern HandleTable g_handle_table; | ||||
| extern Thread* g_main_thread; | ||||
| extern SharedPtr<Thread> g_main_thread; | ||||
| 
 | ||||
| /// The ID code of the currently running game
 | ||||
| /// TODO(Subv): This variable should not be here, 
 | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl | |||
| bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) { | ||||
|     MutexAcquireLock(mutex, thread_handle); | ||||
| 
 | ||||
|     Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle); | ||||
|     Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle).get(); | ||||
|     if (thread == nullptr) { | ||||
|         LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle); | ||||
|         return false; | ||||
|  | @ -94,7 +94,7 @@ void ReleaseThreadMutexes(Handle thread) { | |||
|      | ||||
|     // Release every mutex that the thread holds, and resume execution on the waiting threads
 | ||||
|     for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { | ||||
|         Mutex* mutex = g_handle_table.Get<Mutex>(iter->second); | ||||
|         Mutex* mutex = g_handle_table.Get<Mutex>(iter->second).get(); | ||||
|         ResumeWaitingThread(mutex); | ||||
|     } | ||||
| 
 | ||||
|  | @ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { | |||
|  * @param handle Handle to mutex to release | ||||
|  */ | ||||
| ResultCode ReleaseMutex(Handle handle) { | ||||
|     Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle); | ||||
|     Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get(); | ||||
|     if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     if (!ReleaseMutex(mutex)) { | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count, | |||
| } | ||||
| 
 | ||||
| ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | ||||
|     Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle); | ||||
|     Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); | ||||
|     if (semaphore == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|  | @ -84,7 +84,7 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | |||
|     // Notify some of the threads that the semaphore has been released
 | ||||
|     // stop once the semaphore is full again or there are no more waiting threads
 | ||||
|     while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) { | ||||
|         Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()); | ||||
|         Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()).get(); | ||||
|         if (thread != nullptr) | ||||
|             thread->ResumeFromWait(); | ||||
|         semaphore->waiting_threads.pop(); | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions | |||
|         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | ||||
|                 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||||
|     } | ||||
|     SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); | ||||
|     SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); | ||||
|     if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     shared_memory->base_address = address; | ||||
|  | @ -72,7 +72,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions | |||
| } | ||||
| 
 | ||||
| ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { | ||||
|     SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); | ||||
|     SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); | ||||
|     if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||||
| 
 | ||||
|     if (0 != shared_memory->base_address) | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ ResultVal<bool> Thread::WaitSynchronization() { | |||
| } | ||||
| 
 | ||||
| // Lists all thread ids that aren't deleted/etc.
 | ||||
| static std::vector<Thread*> thread_list; // TODO(yuriks): Owned
 | ||||
| static std::vector<SharedPtr<Thread>> thread_list; | ||||
| 
 | ||||
| // Lists only ready thread ids.
 | ||||
| static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; | ||||
|  | @ -110,8 +110,8 @@ void Thread::Stop(const char* reason) { | |||
| 
 | ||||
|     ChangeReadyState(this, false); | ||||
|     status = THREADSTATUS_DORMANT; | ||||
|     for (Thread* waiting_thread : waiting_threads) { | ||||
|         if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, this)) | ||||
|     for (auto& waiting_thread : waiting_threads) { | ||||
|         if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this)) | ||||
|             waiting_thread->ResumeFromWait(); | ||||
|     } | ||||
|     waiting_threads.clear(); | ||||
|  | @ -143,15 +143,15 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) { | |||
|     s32 priority = THREADPRIO_LOWEST; | ||||
| 
 | ||||
|     // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
 | ||||
|     for (Thread* thread : thread_list) { | ||||
|         if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) | ||||
|     for (auto& thread : thread_list) { | ||||
|         if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | ||||
|             continue; | ||||
| 
 | ||||
|         if (thread == nullptr) | ||||
|             continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
 | ||||
| 
 | ||||
|         if(thread->current_priority <= priority) { | ||||
|             highest_priority_thread = thread; | ||||
|             highest_priority_thread = thread.get(); | ||||
|             priority = thread->current_priority; | ||||
|         } | ||||
|     } | ||||
|  | @ -168,8 +168,8 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) { | |||
| void ArbitrateAllThreads(Object* arbiter, u32 address) { | ||||
| 
 | ||||
|     // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
 | ||||
|     for (Thread* thread : thread_list) { | ||||
|         if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) | ||||
|     for (auto& thread : thread_list) { | ||||
|         if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | ||||
|             thread->ResumeFromWait(); | ||||
|     } | ||||
| } | ||||
|  | @ -241,7 +241,7 @@ static int ThreadWakeupEventType = -1; | |||
| /// Callback that will wake up the thread it was scheduled for
 | ||||
| static void ThreadWakeupCallback(u64 parameter, int cycles_late) { | ||||
|     Handle handle = static_cast<Handle>(parameter); | ||||
|     Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); | ||||
|     SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle); | ||||
|     if (thread == nullptr) { | ||||
|         LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); | ||||
|         return; | ||||
|  | @ -278,20 +278,18 @@ static void DebugThreadQueue() { | |||
|         return; | ||||
|     } | ||||
|     LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); | ||||
|     for (Thread* t : thread_list) { | ||||
|         s32 priority = thread_ready_queue.contains(t); | ||||
|     for (auto& t : thread_list) { | ||||
|         s32 priority = thread_ready_queue.contains(t.get()); | ||||
|         if (priority != -1) { | ||||
|             LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, | ||||
|         s32 processor_id, u32 stack_top, int stack_size) { | ||||
|     _dbg_assert_(Kernel, name != nullptr); | ||||
| 
 | ||||
|     if ((u32)stack_size < 0x200) { | ||||
|         LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name, stack_size); | ||||
| ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | ||||
|         u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size) { | ||||
|     if (stack_size < 0x200) { | ||||
|         LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name.c_str(), stack_size); | ||||
|         // TODO: Verify error
 | ||||
|         return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel, | ||||
|                 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||||
|  | @ -300,27 +298,26 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit | |||
|     if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { | ||||
|         s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | ||||
|             name, priority, new_priority); | ||||
|             name.c_str(), priority, new_priority); | ||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||
|         // validity of this
 | ||||
|         priority = new_priority; | ||||
|     } | ||||
| 
 | ||||
|     if (!Memory::GetPointer(entry_point)) { | ||||
|         LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); | ||||
|         LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); | ||||
|         // TODO: Verify error
 | ||||
|         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | ||||
|                 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||||
|     } | ||||
| 
 | ||||
|     Thread* thread = new Thread; | ||||
|     SharedPtr<Thread> thread(new Thread); | ||||
| 
 | ||||
|     // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
 | ||||
|     //               the time being. Create a handle here, it will be copied to the handle field in
 | ||||
|     //               the object and use by the rest of the code. This should be removed when other
 | ||||
|     //               code doesn't rely on the handle anymore.
 | ||||
|     ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); | ||||
|     // TODO(yuriks): Plug memory leak
 | ||||
|     if (handle.Failed()) | ||||
|         return handle.Code(); | ||||
| 
 | ||||
|  | @ -337,12 +334,12 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit | |||
|     thread->wait_type = WAITTYPE_NONE; | ||||
|     thread->wait_object = nullptr; | ||||
|     thread->wait_address = 0; | ||||
|     thread->name = name; | ||||
|     thread->name = std::move(name); | ||||
| 
 | ||||
|     ResetThread(thread, arg, 0); | ||||
|     CallThread(thread); | ||||
|     ResetThread(thread.get(), arg, 0); | ||||
|     CallThread(thread.get()); | ||||
| 
 | ||||
|     return MakeResult<Thread*>(thread); | ||||
|     return MakeResult<SharedPtr<Thread>>(std::move(thread)); | ||||
| } | ||||
| 
 | ||||
| /// Set the priority of the thread specified by handle
 | ||||
|  | @ -376,20 +373,20 @@ Handle SetupIdleThread() { | |||
|     auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, | ||||
|             THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); | ||||
|     _dbg_assert_(Kernel, thread_res.Succeeded()); | ||||
|     Thread* thread = *thread_res; | ||||
|     SharedPtr<Thread> thread = std::move(*thread_res); | ||||
| 
 | ||||
|     thread->idle = true; | ||||
|     CallThread(thread); | ||||
|     CallThread(thread.get()); | ||||
|     return thread->GetHandle(); | ||||
| } | ||||
| 
 | ||||
| Thread* SetupMainThread(s32 priority, int stack_size) { | ||||
| SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { | ||||
|     // Initialize new "main" thread
 | ||||
|     ResultVal<Thread*> thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, | ||||
|         THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); | ||||
|     auto thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, | ||||
|             THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); | ||||
|     // TODO(yuriks): Propagate error
 | ||||
|     _dbg_assert_(Kernel, thread_res.Succeeded()); | ||||
|     Thread* thread = *thread_res; | ||||
|     SharedPtr<Thread> thread = std::move(*thread_res); | ||||
| 
 | ||||
|     // If running another thread already, set it to "ready" state
 | ||||
|     Thread* cur = GetCurrentThread(); | ||||
|  | @ -398,7 +395,7 @@ Thread* SetupMainThread(s32 priority, int stack_size) { | |||
|     } | ||||
| 
 | ||||
|     // Run new "main" thread
 | ||||
|     current_thread = thread; | ||||
|     current_thread = thread.get(); | ||||
|     thread->status = THREADSTATUS_RUNNING; | ||||
|     Core::g_app_core->LoadContext(thread->context); | ||||
| 
 | ||||
|  | @ -418,7 +415,7 @@ void Reschedule() { | |||
|     } else { | ||||
|         LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); | ||||
| 
 | ||||
|         for (Thread* thread : thread_list) { | ||||
|         for (auto& thread : thread_list) { | ||||
|             LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", | ||||
|                 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, | ||||
|                 (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE)); | ||||
|  |  | |||
|  | @ -54,8 +54,8 @@ namespace Kernel { | |||
| 
 | ||||
| class Thread : public Kernel::Object { | ||||
| public: | ||||
|     static ResultVal<Thread*> Create(const char* name, u32 entry_point, s32 priority, u32 arg, | ||||
|         s32 processor_id, u32 stack_top, int stack_size = Kernel::DEFAULT_STACK_SIZE); | ||||
|     static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, | ||||
|         u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); | ||||
| 
 | ||||
|     std::string GetName() const override { return name; } | ||||
|     std::string GetTypeName() const override { return "Thread"; } | ||||
|  | @ -99,7 +99,7 @@ public: | |||
|     Object* wait_object; | ||||
|     VAddr wait_address; | ||||
| 
 | ||||
|     std::vector<Thread*> waiting_threads; // TODO(yuriks): Owned
 | ||||
|     std::vector<SharedPtr<Thread>> waiting_threads; | ||||
| 
 | ||||
|     std::string name; | ||||
| 
 | ||||
|  | @ -111,7 +111,7 @@ private: | |||
| }; | ||||
| 
 | ||||
| /// Sets up the primary application thread
 | ||||
| Thread* SetupMainThread(s32 priority, int stack_size = Kernel::DEFAULT_STACK_SIZE); | ||||
| SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); | ||||
| 
 | ||||
| /// Reschedules to the next available thread (call after current thread is suspended)
 | ||||
| void Reschedule(); | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::st | |||
| } | ||||
| 
 | ||||
| ResultCode ClearTimer(Handle handle) { | ||||
|     Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
|      | ||||
|     if (timer == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
|  | @ -80,7 +80,7 @@ static int TimerCallbackEventType = -1; | |||
| 
 | ||||
| /// The timer callback event, called when a timer is fired
 | ||||
| static void TimerCallback(u64 timer_handle, int cycles_late) { | ||||
|     Timer* timer = Kernel::g_handle_table.Get<Timer>(timer_handle); | ||||
|     SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); | ||||
| 
 | ||||
|     if (timer == nullptr) { | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); | ||||
|  | @ -93,7 +93,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { | |||
| 
 | ||||
|     // Resume all waiting threads
 | ||||
|     for (Handle thread_handle : timer->waiting_threads) { | ||||
|         if (Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) | ||||
|         if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) | ||||
|             thread->ResumeFromWait(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -111,7 +111,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { | |||
| } | ||||
| 
 | ||||
| ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { | ||||
|     Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
| 
 | ||||
|     if (timer == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
|  | @ -125,7 +125,7 @@ ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { | |||
| } | ||||
| 
 | ||||
| ResultCode CancelTimer(Handle handle) { | ||||
|     Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); | ||||
| 
 | ||||
|     if (timer == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
|  |  | |||
|  | @ -59,7 +59,8 @@ void Manager::DeleteService(const std::string& port_name) { | |||
| } | ||||
| 
 | ||||
| Interface* Manager::FetchFromHandle(Handle handle) { | ||||
|     return Kernel::g_handle_table.Get<Interface>(handle); | ||||
|     // TODO(yuriks): This function is very suspicious and should probably be exterminated.
 | ||||
|     return Kernel::g_handle_table.Get<Interface>(handle).get(); | ||||
| } | ||||
| 
 | ||||
| Interface* Manager::FetchFromPortName(const std::string& port_name) { | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ | |||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Namespace SVC
 | ||||
| 
 | ||||
| using Kernel::SharedPtr; | ||||
| 
 | ||||
| namespace SVC { | ||||
| 
 | ||||
| enum ControlMemoryOperation { | ||||
|  | @ -94,7 +96,7 @@ static Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 
 | ||||
| /// Synchronize to an OS service
 | ||||
| static Result SendSyncRequest(Handle handle) { | ||||
|     Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle); | ||||
|     SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); | ||||
|     if (session == nullptr) { | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
|     } | ||||
|  | @ -121,12 +123,12 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
|     // TODO(bunnei): Do something with nano_seconds, currently ignoring this
 | ||||
|     bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
 | ||||
| 
 | ||||
|     Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle); | ||||
|     SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle); | ||||
|     if (object == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), | ||||
|             object->GetName().c_str(), nano_seconds); | ||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, | ||||
|             object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); | ||||
| 
 | ||||
|     ResultVal<bool> wait = object->WaitSynchronization(); | ||||
| 
 | ||||
|  | @ -151,12 +153,12 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 
 | ||||
|     // Iterate through each handle, synchronize kernel object
 | ||||
|     for (s32 i = 0; i < handle_count; i++) { | ||||
|         Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]); | ||||
|         SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handles[i]); | ||||
|         if (object == nullptr) | ||||
|             return InvalidHandle(ErrorModule::Kernel).raw; | ||||
| 
 | ||||
|         LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), | ||||
|             object->GetName().c_str()); | ||||
|         LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], | ||||
|                 object->GetTypeName().c_str(), object->GetName().c_str()); | ||||
| 
 | ||||
|         // TODO(yuriks): Verify how the real function behaves when an error happens here
 | ||||
|         ResultVal<bool> wait_result = object->WaitSynchronization(); | ||||
|  | @ -223,6 +225,8 @@ static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, | |||
| 
 | ||||
| /// Creates a new thread
 | ||||
| static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { | ||||
|     using Kernel::Thread; | ||||
| 
 | ||||
|     std::string name; | ||||
|     if (Symbols::HasSymbol(entry_point)) { | ||||
|         TSymbol symbol = Symbols::GetSymbol(entry_point); | ||||
|  | @ -231,12 +235,13 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top | |||
|         name = Common::StringFromFormat("unknown-%08x", entry_point); | ||||
|     } | ||||
| 
 | ||||
|     ResultVal<Kernel::Thread*> thread_res = Kernel::Thread::Create(name.c_str(), entry_point, priority, arg, | ||||
|             processor_id, stack_top); | ||||
|     ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create( | ||||
|             name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); | ||||
|     if (thread_res.Failed()) | ||||
|         return thread_res.Code().raw; | ||||
|     Kernel::Thread* thread = *thread_res; | ||||
|     SharedPtr<Thread> thread = std::move(*thread_res); | ||||
| 
 | ||||
|     // TODO(yuriks): Create new handle instead of using built-in
 | ||||
|     Core::g_app_core->SetReg(1, thread->GetHandle()); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | ||||
|  | @ -261,7 +266,7 @@ static void ExitThread() { | |||
| 
 | ||||
| /// Gets the priority for the specified thread
 | ||||
| static Result GetThreadPriority(s32* priority, Handle handle) { | ||||
|     const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
| 
 | ||||
|  | @ -271,7 +276,7 @@ static Result GetThreadPriority(s32* priority, Handle handle) { | |||
| 
 | ||||
| /// Sets the priority for the specified thread
 | ||||
| static Result SetThreadPriority(Handle handle, s32 priority) { | ||||
|     Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
| 
 | ||||
|  | @ -298,7 +303,7 @@ static Result ReleaseMutex(Handle handle) { | |||
| static Result GetThreadId(u32* thread_id, Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); | ||||
| 
 | ||||
|     const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel).raw; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue