ksys/frm: Implement WorkerSupportThreadMgr

This commit is contained in:
Léo Lam 2021-04-26 15:59:49 +02:00
parent caa3dcf548
commit 927c757345
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
4 changed files with 226 additions and 14 deletions

View File

@ -39801,7 +39801,7 @@
0x000000710065a290,sub_710065A290,8,
0x000000710065a298,sub_710065A298,48,
0x000000710065a2c8,sub_710065A2C8,92,
0x000000710065a324,sub_710065A324,8,
0x000000710065a324,sub_710065A324,8,_ZNK4sead10IDelegate2IPNS_6ThreadElE9isNoDummyEv
0x000000710065a32c,sub_710065A32C,8,_ZNK4sead10IDelegate2IPNS_6ThreadElE5cloneEPNS_4HeapE
0x000000710065a334,sub_710065A334,48,
0x000000710065a364,sub_710065A364,92,
@ -75989,19 +75989,19 @@
0x0000007100dcde30,sub_7100DCDE30,92,
0x0000007100dcde8c,sub_7100DCDE8C,52,
0x0000007100dcdec0,sub_7100DCDEC0,92,
0x0000007100dcdf1c,sub_7100DCDF1C,56,
0x0000007100dcdf54,sub_7100DCDF54,92,
0x0000007100dcdfb0,WorkerSupportThreadMgr::createInstance,276,
0x0000007100dce0c4,WorkerSupportThreadMgr::init,656,
0x0000007100dce354,WorkerSupportThreadMgr::startSleeperThread,588,
0x0000007100dce5a0,SleeperThreadFunc,44,
0x0000007100dce5cc,WorkerSupportThreadMgr::submitReq,240,
0x0000007100dce6bc,WorkerSupportThreadMgr::__auto0,68,
0x0000007100dce700,WorkerSupportThreadMgr::__auto3,48,
0x0000007100dce730,WorkerSupportThreadMgr::__auto1,44,
0x0000007100dce75c,WorkerSupportThreadMgr::__auto2,136,
0x0000007100dce7e8,sub_7100DCE7E8,48,
0x0000007100dce818,sub_7100DCE818,92,
0x0000007100dcdf1c,sub_7100DCDF1C,56,_ZN4ksys3frm22WorkerSupportThreadMgr18SingletonDisposer_D1Ev
0x0000007100dcdf54,sub_7100DCDF54,92,_ZN4ksys3frm22WorkerSupportThreadMgr18SingletonDisposer_D0Ev
0x0000007100dcdfb0,WorkerSupportThreadMgr::createInstance,276,_ZN4ksys3frm22WorkerSupportThreadMgr14createInstanceEPN4sead4HeapE
0x0000007100dce0c4,WorkerSupportThreadMgr::init,656,_ZN4ksys3frm22WorkerSupportThreadMgr4initEPN4sead4HeapE
0x0000007100dce354,WorkerSupportThreadMgr::startSleeperThread,588,_ZN4ksys3frm22WorkerSupportThreadMgr18initSleeperThreadsEv
0x0000007100dce5a0,SleeperThreadFunc,44,_ZN4ksys3frm22WorkerSupportThreadMgr16sleeperThreadFunEPN4sead6ThreadEl
0x0000007100dce5cc,WorkerSupportThreadMgr::submitReq,240,_ZN4ksys3frm22WorkerSupportThreadMgr13submitRequestEiPN4sead11IDelegate1RIPvbEE
0x0000007100dce6bc,WorkerSupportThreadMgr::__auto0,68,_ZN4ksys3frm22WorkerSupportThreadMgr11waitForTaskEi
0x0000007100dce700,WorkerSupportThreadMgr::__auto3,48,_ZN4ksys3frm22WorkerSupportThreadMgr12pauseThreadsEv
0x0000007100dce730,WorkerSupportThreadMgr::__auto1,44,_ZN4ksys3frm22WorkerSupportThreadMgr13resumeThreadsEv
0x0000007100dce75c,WorkerSupportThreadMgr::__auto2,136,_ZN4ksys3frm22WorkerSupportThreadMgr14destroyThreadsEv
0x0000007100dce7e8,sub_7100DCE7E8,48,_ZN4sead9Delegate2IN4ksys3frm22WorkerSupportThreadMgrEPNS_6ThreadElE6invokeES5_l
0x0000007100dce818,sub_7100DCE818,92,_ZNK4sead9Delegate2IN4ksys3frm22WorkerSupportThreadMgrEPNS_6ThreadElE5cloneEPNS_4HeapE
0x0000007100dce874,sub_7100DCE874,32,
0x0000007100dce894,sub_7100DCE894,100,_ZN4ksys3gdt7Manager18SingletonDisposer_D1Ev
0x0000007100dce8f8,sub_7100DCE8F8,108,_ZN4ksys3gdt7Manager18SingletonDisposer_D0Ev

Can't render this file because it is too large.

View File

@ -1,3 +1,5 @@
target_sources(uking PRIVATE
frmRootTaskParam.h
frmWorkerSupportThreadMgr.cpp
frmWorkerSupportThreadMgr.h
)

View File

@ -0,0 +1,138 @@
#include "KingSystem/Framework/frmWorkerSupportThreadMgr.h"
#include <mc/seadCoreInfo.h>
#include <thread/seadDelegateThread.h>
#include <thread/seadThreadUtil.h>
#include "KingSystem/Utils/SafeDelete.h"
#include "KingSystem/Utils/Thread/GameTaskThread.h"
#include "KingSystem/Utils/Thread/ManagedTask.h"
#include "KingSystem/Utils/Thread/ManagedTaskHandle.h"
#include "KingSystem/Utils/Thread/TaskMgr.h"
namespace ksys::frm {
SEAD_SINGLETON_DISPOSER_IMPL(WorkerSupportThreadMgr)
void WorkerSupportThreadMgr::init(sead::Heap* heap) {
auto* worker = mWorkers;
for (size_t i = 0; i < NumWorkers; ++i) {
auto* mgr = new (heap) util::TaskMgr(heap);
mgr->init<util::ManagedTask>(NumTasks, heap);
worker->task_mgr = mgr;
worker->task_handle = new (heap) util::ManagedTaskHandle;
for (int j = 0; j < NumTasks; ++j)
worker->tasks[j] = new (heap) util::ManagedTask(heap);
const auto affinity = [&] {
if (i == 0)
return sead::CoreIdMask(sead::CoreId::cSub1);
return sead::CoreIdMask(sead::CoreId::cSub2);
}();
worker->thread_name.format("WorkerSupport[%d]", int(i));
worker->task_thread = new (heap) util::GameTaskThread(
worker->thread_name, heap, sead::ThreadUtil::ConvertPrioritySeadToPlatform(17),
sead::MessageQueue::BlockType::Blocking, 0x7fffffff, 0x20000, 32);
util::TaskThread::InitArg arg;
arg.batch_size = 0;
arg.heap = nullptr;
arg.queue = nullptr;
arg.heap = heap;
arg.num_lanes = 1;
worker->task_thread->init(arg);
worker->task_thread->setAffinity(affinity);
worker->task_thread->start();
++worker;
}
mSleeperHeap = sead::ExpHeap::create(0x8000, "SleeperHeap", heap, sizeof(void*),
sead::Heap::cHeapDirection_Forward, false);
initSleeperThreads();
mSleeperHeap->adjust();
}
void WorkerSupportThreadMgr::initSleeperThreads() {
for (int i = 0; i < NumWorkers; ++i) {
const sead::CoreIdMask affinity{sead::CoreId::cSub1 + i};
if (affinity == sead::CoreIdMask(sead::CoreId::cSub2)) {
mWorkers[i].thread = new (mSleeperHeap) sead::DelegateThread(
"Sleeper",
new (mSleeperHeap) sead::Delegate2<WorkerSupportThreadMgr, sead::Thread*,
sead::MessageQueue::Element>(
this, &WorkerSupportThreadMgr::sleeperThreadFun),
mSleeperHeap, sead::ThreadUtil::ConvertPrioritySeadToPlatform(15),
sead::MessageQueue::BlockType::NonBlocking, 0x7fffffff, 0x1000, 32);
mWorkers[i].thread->setAffinity(affinity);
mWorkers[i].thread->start();
mWorkers[i].thread->sendMessage(1, sead::MessageQueue::BlockType::NonBlocking);
} else {
mWorkers[i].thread = nullptr;
}
}
}
void WorkerSupportThreadMgr::sleeperThreadFun(sead::Thread* thread, sead::MessageQueue::Element) {
sead::Thread::sleep(sead::TickSpan::fromMicroSeconds(250));
}
static int getWorkerIdx(u32 id) {
return (id == 1 || id == 4 || id == 6 || id == 3 || id == 7) ? 1 : 0;
}
static int getTaskIdx(u32 id) {
static constexpr u8 idx[] = {0, 0, 1, 1, 2, 2, 3, 4};
return idx[id];
}
util::ManagedTask* WorkerSupportThreadMgr::getTask(int id) {
return mWorkers[getWorkerIdx(id)].tasks[getTaskIdx(id)];
}
void WorkerSupportThreadMgr::submitRequest(int id, util::TaskDelegate* delegate) {
auto& worker = mWorkers[getWorkerIdx(id)];
if (mThreadsPaused)
return;
util::TaskRequest req{false};
req.mName = worker.thread_name;
req.mDelegate = delegate;
req.mHasHandle = true;
req.mSynchronous = false;
req.mThread = worker.task_thread;
util::TaskMgrRequest task_mgr_req;
task_mgr_req.request = &req;
task_mgr_req.handle = worker.task_handle;
task_mgr_req.task = worker.tasks[getTaskIdx(id)];
worker.task_mgr->submitRequest(task_mgr_req);
}
void WorkerSupportThreadMgr::waitForTask(int id) {
if (!mThreadsPaused)
getTask(id)->wait();
}
void WorkerSupportThreadMgr::pauseThreads() {
mThreadsPaused = true;
for (auto& worker : mWorkers)
worker.task_thread->pauseAndWaitForAck();
}
void WorkerSupportThreadMgr::resumeThreads() {
mThreadsPaused = false;
for (auto& worker : mWorkers)
worker.task_thread->resume();
}
void WorkerSupportThreadMgr::destroyThreads() {
for (auto& worker : mWorkers) {
if (worker.thread) {
worker.thread->quitAndDestroySingleThread(false);
util::safeDelete(worker.thread);
}
}
mSleeperHeap->freeAll();
}
} // namespace ksys::frm

View File

@ -0,0 +1,72 @@
#pragma once
#include <heap/seadDisposer.h>
#include <prim/seadSafeString.h>
#include <thread/seadMessageQueue.h>
#include "KingSystem/Utils/Thread/Task.h"
#include "KingSystem/Utils/Types.h"
namespace sead {
class DelegateThread;
class Thread;
} // namespace sead
namespace ksys::util {
class GameTaskThread;
class ManagedTask;
class ManagedTaskHandle;
class TaskMgr;
} // namespace ksys::util
namespace ksys::frm {
class WorkerSupportThreadMgr {
SEAD_SINGLETON_DISPOSER(WorkerSupportThreadMgr)
WorkerSupportThreadMgr() = default;
~WorkerSupportThreadMgr() = default;
public:
enum class Owner {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
};
void init(sead::Heap* heap);
void submitRequest(int id, util::TaskDelegate* delegate);
void waitForTask(int id);
void pauseThreads();
void resumeThreads();
void destroyThreads();
private:
static constexpr int NumWorkers = 2;
static constexpr int NumTasks = 5;
struct Worker {
util::GameTaskThread* task_thread = nullptr;
sead::DelegateThread* thread;
util::ManagedTask* tasks[NumTasks];
util::TaskMgr* task_mgr = nullptr;
util::ManagedTaskHandle* task_handle;
sead::FixedSafeString<32> thread_name;
};
void initSleeperThreads();
void sleeperThreadFun(sead::Thread* thread, sead::MessageQueue::Element);
util::ManagedTask* getTask(int id);
Worker mWorkers[NumWorkers];
bool mThreadsPaused = false;
sead::Heap* mSleeperHeap;
};
KSYS_CHECK_SIZE_NX150(WorkerSupportThreadMgr, 0x130);
} // namespace ksys::frm