diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 99219872..fb67759d 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -94620,18 +94620,18 @@ Address,Quality,Size,Name 0x000000710127a374,O,000052,_ZN4sead10Delegate1RIN4ksys3act15BaseProcDeleterEPvbE6invokeES4_ 0x000000710127a3a8,O,000092,_ZNK4sead10Delegate1RIN4ksys3act15BaseProcDeleterEPvbE5cloneEPNS_4HeapE 0x000000710127a404,U,000080, -0x000000710127a454,U,000100, -0x000000710127a4b8,U,000108, -0x000000710127a524,U,000152,LowPrioThreadMgr::createInstance -0x000000710127a5bc,U,000256, -0x000000710127a6bc,U,000252, -0x000000710127a7b8,U,000508,LowPrioThreadMgr::startThread -0x000000710127a9b4,U,000412,LowPrioThreadMgr::submitRequest -0x000000710127ab50,U,000120, -0x000000710127abc8,U,000120, -0x000000710127ac40,U,000004,nullsub_6155 -0x000000710127ac44,U,000112, -0x000000710127acb4,U,000092, +0x000000710127a454,O,000100,_ZN4ksys4util16LowPrioThreadMgr18SingletonDisposer_D1Ev +0x000000710127a4b8,O,000108,_ZN4ksys4util16LowPrioThreadMgr18SingletonDisposer_D0Ev +0x000000710127a524,O,000152,_ZN4ksys4util16LowPrioThreadMgr14createInstanceEPN4sead4HeapE +0x000000710127a5bc,O,000256,_ZN4ksys4util16LowPrioThreadMgrD1Ev +0x000000710127a6bc,O,000252,_ZN4ksys4util16LowPrioThreadMgrD0Ev +0x000000710127a7b8,O,000508,_ZN4ksys4util16LowPrioThreadMgr11startThreadERKNS1_7InitArgE +0x000000710127a9b4,O,000412,_ZN4ksys4util16LowPrioThreadMgr13submitRequestERKNS1_7RequestE +0x000000710127ab50,O,000120,_ZN4ksys4util16LowPrioThreadMgr13pauseAllTasksEv +0x000000710127abc8,O,000120,_ZN4ksys4util16LowPrioThreadMgr14resumeAllTasksEv +0x000000710127ac40,O,000004,_ZN4ksys4util16LowPrioThreadMgr14sub_710127AC40Ev +0x000000710127ac44,O,000112,_ZNK4ksys4util16LowPrioThreadMgr27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x000000710127acb4,O,000092,_ZNK4ksys4util16LowPrioThreadMgr18getRuntimeTypeInfoEv 0x000000710127ad10,O,000140,_ZN4ksys3res12GameSaveData4File11forEachFlagERKN4sead9Delegate1INS_7SaveMgrERKNS1_4FlagEEE 0x000000710127ad9c,O,000164,_ZN4ksys3res12GameSaveData4File11forEachFlagERKN4sead9Delegate1INS_7SaveMgrERKNS1_4FlagEEEii 0x000000710127ae40,O,000140,_ZN4ksys3res12GameSaveData4File11forEachFlagERKN4sead9Delegate1INS_7SaveMgrERNS1_4FlagEEE diff --git a/src/KingSystem/Utils/CMakeLists.txt b/src/KingSystem/Utils/CMakeLists.txt index ddd23ad8..2f5085e9 100644 --- a/src/KingSystem/Utils/CMakeLists.txt +++ b/src/KingSystem/Utils/CMakeLists.txt @@ -5,6 +5,8 @@ target_sources(uking PRIVATE Thread/Event.h Thread/GameTaskThread.cpp Thread/GameTaskThread.h + Thread/LowPrioThreadMgr.h + Thread/LowPrioThreadMgr.cpp Thread/ManagedTask.cpp Thread/ManagedTask.h Thread/ManagedTaskHandle.cpp diff --git a/src/KingSystem/Utils/Thread/LowPrioThreadMgr.cpp b/src/KingSystem/Utils/Thread/LowPrioThreadMgr.cpp new file mode 100644 index 00000000..35f69e48 --- /dev/null +++ b/src/KingSystem/Utils/Thread/LowPrioThreadMgr.cpp @@ -0,0 +1,119 @@ +#include "KingSystem/Utils/Thread/LowPrioThreadMgr.h" +#include +#include +#include +#include "KingSystem/Utils/SafeDelete.h" +#include "KingSystem/Utils/Thread/TaskQueue.h" + +namespace ksys::util { + +SEAD_SINGLETON_DISPOSER_IMPL(LowPrioThreadMgr) + +LowPrioThreadMgr::~LowPrioThreadMgr() { + const s32 num_tasks = mCoreThreadTasks.size(); + + for (s32 i = 0; i < num_tasks; i++) { + mCoreThreadTasks[i].task_thread->quitAndWaitDoneSingleThread(false); + util::safeDelete(mCoreThreadTasks[i].task_thread); + util::safeDelete(mCoreThreadTasks[i].task_mgr); + } + mCoreThreadTasks.freeBuffer(); +} + +bool LowPrioThreadMgr::startThread(const LowPrioThreadMgr::InitArg& initArg) { + const u32 num_cores = sead::CoreInfo::getNumCores(); + + mCoreThreadTasks.tryAllocBuffer(num_cores, initArg.heap); + + for (u32 i = 0; i < num_cores; i++) { + auto* task_mgr = new (initArg.heap) TaskMgr(initArg.heap); + task_mgr->init(initArg.queue_size, initArg.heap); + mCoreThreadTasks[i].task_mgr = task_mgr; + + sead::SafeString name; + auto* new_thread = new (initArg.heap) TaskThread( + name, initArg.heap, sead::ThreadUtil::ConvertPrioritySeadToPlatform(initArg.priority), + sead::MessageQueue::BlockType::Blocking, std::numeric_limits::max(), 0x100000, 32); + + { + TaskThread::InitArg arg; + + arg.queue = nullptr; + arg.heap = initArg.heap; + arg.num_lanes = 3; + arg.batch_size = 1; + + new_thread->init(arg); + } + + mCoreThreadTasks[i].task_thread = new_thread; + + new_thread->setAffinity(sead::CoreIdMask(i)); + new_thread->start(); + } + + return true; +} + +bool LowPrioThreadMgr::submitRequest(const LowPrioThreadMgr::Request& request) { + const s32 num_tasks = mCoreThreadTasks.size(); + const sead::BitFlag32 mask = request.flags; + s32 thread_idx = -1; + s32 min = std::numeric_limits::max(); + + for (s32 i = 0; i < num_tasks; i++) { + if (mask.isOnBit(i) && mCoreThreadTasks[i].task_thread) { + s32 active_tasks = mCoreThreadTasks[i].task_thread->getNumActiveTasks(); + + if (active_tasks < min) { + thread_idx = i; + min = active_tasks; + } + } + } + + TaskRequest taskRequest(false); + taskRequest.mPostRunCallback = request.post_callback; + taskRequest.mRemoveCallback = request.remove_callback; + taskRequest.mName = request.name; + taskRequest.mUserData = request.user_data; + taskRequest.mDelegate = request.delegate; + taskRequest.mHasHandle = true; + taskRequest.mSynchronous = false; + taskRequest.mLaneId = request.lane_id; + taskRequest.mThread = mCoreThreadTasks[thread_idx].task_thread; + + TaskMgrRequest mgrRequest; + mgrRequest.handle = request.handle; + mgrRequest.request = &taskRequest; + mgrRequest.task = request.task; + + TaskMgr* task_mgr = request.mgr ? request.mgr : mCoreThreadTasks[thread_idx].task_mgr; + + if (request.try_submit) { + return task_mgr->trySubmitRequest(mgrRequest); + } + + task_mgr->submitRequest(mgrRequest); + return true; +} + +void LowPrioThreadMgr::pauseAllTasks() { + const s32 num_tasks = mCoreThreadTasks.size(); + + for (s32 i = 0; i < num_tasks; i++) { + mCoreThreadTasks[i].task_thread->pauseAndWaitForAck(); + } +} + +void LowPrioThreadMgr::resumeAllTasks() { + const s32 num_tasks = mCoreThreadTasks.size(); + + for (s32 i = 0; i < num_tasks; i++) { + mCoreThreadTasks[i].task_thread->resume(); + } +} + +void LowPrioThreadMgr::sub_710127AC40() {} + +} // namespace ksys::util diff --git a/src/KingSystem/Utils/Thread/LowPrioThreadMgr.h b/src/KingSystem/Utils/Thread/LowPrioThreadMgr.h new file mode 100644 index 00000000..08ddfe85 --- /dev/null +++ b/src/KingSystem/Utils/Thread/LowPrioThreadMgr.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Utils/Thread/Task.h" +#include "KingSystem/Utils/Thread/TaskMgr.h" +#include "KingSystem/Utils/Thread/TaskThread.h" + +namespace ksys::util { + +class LowPrioThreadMgr { + SEAD_SINGLETON_DISPOSER(LowPrioThreadMgr) + SEAD_RTTI_BASE(LowPrioThreadMgr) + +public: + struct InitArg { + sead::Heap* heap; + s32 priority; + s32 queue_size; + }; + KSYS_CHECK_SIZE_NX150(InitArg, 0x10); + + struct CoreThreadTask { + TaskThread* task_thread{}; + TaskMgr* task_mgr{}; + }; + KSYS_CHECK_SIZE_NX150(CoreThreadTask, 0x10); + + struct Request { + bool try_submit; + s32 lane_id; + sead::BitFlag32 flags; + TaskDelegate* delegate; + void* user_data; + TaskRemoveCallback* remove_callback; + TaskPostRunCallback* post_callback; + ManagedTask* task; + TaskMgr* mgr; + ManagedTaskHandle* handle; + sead::SafeString name; + }; + KSYS_CHECK_SIZE_NX150(Request, 0x58); + + LowPrioThreadMgr() = default; + virtual ~LowPrioThreadMgr(); + + bool startThread(const LowPrioThreadMgr::InitArg& initArg); + bool submitRequest(const LowPrioThreadMgr::Request& request); + void pauseAllTasks(); + void resumeAllTasks(); + void sub_710127AC40(); + +private: + sead::Buffer mCoreThreadTasks{}; +}; + +} // namespace ksys::util