mirror of
https://github.com/encounter/mkdd.git
synced 2026-03-30 11:30:02 -07:00
409 lines
11 KiB
C++
409 lines
11 KiB
C++
#include <stdio.h>
|
|
|
|
#include <dolphin/os.h>
|
|
#include "JSystem/JUtility/JUTDbg.h"
|
|
#include "JSystem/JKernel/JKRHeap.h"
|
|
#include "JSystem/JKernel/JKRThread.h"
|
|
#include "JSystem/JKernel/JKRDisposer.h"
|
|
#include "JSystem/JSupport/JSUList.h"
|
|
#include "types.h"
|
|
|
|
// this file has some unused strings that need to be generated by ppcdis or fake functions
|
|
|
|
JSUList<JKRThread> JKRThread::sThreadList(false);
|
|
JSUList<JKRTask> JKRTask::sTaskList;
|
|
OSMessageQueue JKRTask::sEndMesgQueue;
|
|
|
|
JKRIdleThread *JKRIdleThread::sThread; // Unused
|
|
JKRThreadSwitch *JKRThreadSwitch::sManager;
|
|
u32 JKRThreadSwitch::sTotalCount; // Unused
|
|
u64 JKRThreadSwitch::sTotalStart; // Unused
|
|
JKRThreadSwitch_PreCallback JKRThreadSwitch::mUserPreCallback; // Unused
|
|
JKRThreadSwitch_PostCallback JKRThreadSwitch::mUserPostCallback; // Unused
|
|
OSMessage *JKRTask::sEndMesgBuffer; // Unused
|
|
u32 JKRTask::sEndMesgBufSize; // Unused
|
|
|
|
JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this)
|
|
{
|
|
JKRHeap *heap = JKRHeap::findFromRoot(this);
|
|
if (heap == nullptr)
|
|
{
|
|
heap = JKRHeap::getSystemHeap();
|
|
}
|
|
|
|
setCommon_heapSpecified(heap, stack_size, param_3);
|
|
setCommon_mesgQueue(mHeap, message_count);
|
|
}
|
|
|
|
JKRThread::JKRThread(JKRHeap *heap, u32 stack_size, int message_count, int param_4)
|
|
: mThreadListLink(this)
|
|
{
|
|
if (heap == nullptr)
|
|
{
|
|
heap = JKRHeap::getCurrentHeap();
|
|
}
|
|
|
|
setCommon_heapSpecified(heap, stack_size, param_4);
|
|
setCommon_mesgQueue(mHeap, message_count);
|
|
}
|
|
|
|
JKRThread::JKRThread(OSThread *thread, int message_count) : mThreadListLink(this)
|
|
{
|
|
mHeap = nullptr;
|
|
mThreadRecord = thread;
|
|
mStackSize = (u32)thread->stackEnd - (u32)thread->stackBase;
|
|
mStackMemory = thread->stackBase;
|
|
|
|
setCommon_mesgQueue(JKRHeap::getSystemHeap(), message_count);
|
|
}
|
|
|
|
JKRThread::~JKRThread()
|
|
{
|
|
sThreadList.remove(&mThreadListLink);
|
|
if (mHeap != nullptr)
|
|
{
|
|
if (!OSIsThreadTerminated(mThreadRecord))
|
|
{
|
|
OSDetachThread(mThreadRecord);
|
|
OSCancelThread(mThreadRecord);
|
|
}
|
|
JKRFreeToHeap(mHeap, mStackMemory);
|
|
JKRFreeToHeap(mHeap, mThreadRecord);
|
|
}
|
|
JKRFree(mMesgBuffer);
|
|
}
|
|
|
|
void JKRThread::setCommon_mesgQueue(JKRHeap *heap, int msgCount)
|
|
{
|
|
#line 128
|
|
mMessageCount = msgCount;
|
|
mMesgBuffer = (OSMessage *)JKRHeap::alloc(mMessageCount << 2, 0, heap);
|
|
JUT_ASSERT(mMesgBuffer);
|
|
|
|
OSInitMessageQueue(&mMessageQueue, mMesgBuffer, mMessageCount);
|
|
JKRThread::sThreadList.append(&mThreadListLink);
|
|
mCurrentHeap = nullptr;
|
|
mCurrentHeapError = nullptr;
|
|
}
|
|
|
|
BOOL JKRThread::setCommon_heapSpecified(JKRHeap *heap, u32 stackSize, int threadPriority)
|
|
{
|
|
#line 161
|
|
mHeap = heap;
|
|
mStackSize = stackSize & ~0x1F;
|
|
mStackMemory = JKRHeap::alloc(mStackSize, 0x20, mHeap);
|
|
JUT_ASSERT(mStackMemory);
|
|
|
|
#line 167
|
|
mThreadRecord = (OSThread *)JKRHeap::alloc(sizeof(OSThread), 0x20, mHeap);
|
|
JUT_ASSERT(mThreadRecord);
|
|
return OSCreateThread(mThreadRecord, &JKRThread::start, this, (void *)((u32)mStackMemory + mStackSize), mStackSize, threadPriority, 1);
|
|
}
|
|
|
|
void *JKRThread::start(void *thread) { return static_cast<JKRThread *>(thread)->run(); }
|
|
|
|
JKRThread *JKRThread::searchThread(OSThread *thread)
|
|
{
|
|
JSUList<JKRThread> &threadList = getList();
|
|
JSUListIterator<JKRThread> iterator;
|
|
for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator)
|
|
{
|
|
if (iterator->getThreadRecord() == thread)
|
|
{
|
|
return iterator.getObject();
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
CW_FORCE_STRINGS(JKRThread_1, "JKRThread:%x OSThread:%x Load:ID:%d (%s)\n", "sThread == 0")
|
|
#endif
|
|
|
|
JKRThreadSwitch::JKRThreadSwitch(JKRHeap *heap)
|
|
{
|
|
mHeap = heap;
|
|
OSSetSwitchThreadCallback(JKRThreadSwitch::callback);
|
|
_0C = 0;
|
|
_10 = 1;
|
|
_18 = 0;
|
|
sTotalCount = 0;
|
|
sTotalStart = 0;
|
|
mConsole = nullptr;
|
|
mThreadName = nullptr;
|
|
mSetNextHeap = true;
|
|
}
|
|
|
|
JKRThreadSwitch *JKRThreadSwitch::createManager(JKRHeap *heap)
|
|
{
|
|
#line 343
|
|
JUT_ASSERT(sManager == 0);
|
|
|
|
if (!heap)
|
|
{
|
|
heap = JKRGetCurrentHeap();
|
|
}
|
|
|
|
sManager = new (heap, 0) JKRThreadSwitch(heap);
|
|
return sManager;
|
|
}
|
|
|
|
JKRThread *JKRThreadSwitch::enter(JKRThread *thread, int id)
|
|
{
|
|
if (thread == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
JKRThread *nextThread = JKRThread::searchThread(thread->getThreadRecord());
|
|
if (nextThread != nullptr)
|
|
thread = nextThread;
|
|
|
|
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
|
|
loadInfo->clear();
|
|
loadInfo->setValid(true);
|
|
loadInfo->setId(id);
|
|
}
|
|
return thread;
|
|
}
|
|
|
|
void JKRThreadSwitch::callback(OSThread *current, OSThread *next)
|
|
{
|
|
if (mUserPreCallback)
|
|
{
|
|
(*mUserPreCallback)(current, next);
|
|
}
|
|
|
|
sTotalCount = sTotalCount + 1;
|
|
|
|
JKRHeap *next_heap = nullptr;
|
|
JSUList<JKRThread> &threadList = JKRThread::getList();
|
|
JSUListIterator<JKRThread> iterator;
|
|
for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator)
|
|
{
|
|
JKRThread *thread = iterator.getObject();
|
|
|
|
if (thread->getThreadRecord() == current)
|
|
{
|
|
thread->setCurrentHeap(JKRHeap::getCurrentHeap());
|
|
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
|
|
if (loadInfo->isValid())
|
|
{
|
|
loadInfo->addCurrentCost();
|
|
}
|
|
}
|
|
|
|
if (thread->getThreadRecord() == next)
|
|
{
|
|
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
|
|
if (loadInfo->isValid())
|
|
{
|
|
loadInfo->setCurrentTime();
|
|
loadInfo->incCount();
|
|
}
|
|
|
|
if (sManager->mSetNextHeap)
|
|
{
|
|
next_heap = thread->getCurrentHeap();
|
|
if (!next_heap)
|
|
{
|
|
next_heap = JKRHeap::getCurrentHeap();
|
|
}
|
|
else if (JKRHeap::getRootHeap()->isSubHeap(next_heap))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
switch (thread->getCurrentHeapError())
|
|
{
|
|
case 0:
|
|
#line 508
|
|
JUT_PANIC("JKRThreadSwitch: currentHeap destroyed.");
|
|
break;
|
|
case 1:
|
|
JUTWarningConsole("JKRThreadSwitch: currentHeap destroyed.\n");
|
|
next_heap = JKRHeap::getCurrentHeap();
|
|
break;
|
|
case 2:
|
|
next_heap = JKRHeap::getCurrentHeap();
|
|
break;
|
|
case 3:
|
|
next_heap = JKRHeap::getSystemHeap();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (next_heap)
|
|
{
|
|
next_heap->becomeCurrentHeap();
|
|
}
|
|
|
|
if (mUserPostCallback)
|
|
{
|
|
(*mUserPostCallback)(current, next);
|
|
}
|
|
}
|
|
|
|
void JKRThreadSwitch::draw(JKRThreadName_ *thread_name_list, JUTConsole *console)
|
|
{
|
|
const char *print_0 = " total: switch:%3d time:%d(%df)\n";
|
|
const char *print_1 = " -------------------------------------\n";
|
|
|
|
if (!console)
|
|
{
|
|
/*#if DEBUG
|
|
OSReport(print_0, getTotalCount(), (int)_18, _10);
|
|
OSReport(print_1);
|
|
#endif*/
|
|
}
|
|
else
|
|
{
|
|
console->clear();
|
|
console->print_f(print_0, getTotalCount(), (int)_18, _10);
|
|
console->print(print_1);
|
|
}
|
|
|
|
for (JSUListIterator<JKRThread> iterator = JKRThread::getList().getFirst(); iterator != JKRThread::getList().getEnd(); ++iterator)
|
|
{
|
|
JKRThread *thread = iterator.getObject();
|
|
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
|
|
|
|
if (loadInfo->isValid())
|
|
{
|
|
char *thread_print_name = nullptr;
|
|
if (thread_name_list)
|
|
{
|
|
JKRThreadName_ *thread_name = thread_name_list;
|
|
for (; thread_name->name; thread_name++)
|
|
{
|
|
if (thread_name->id == loadInfo->getId())
|
|
{
|
|
thread_print_name = thread_name->name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!thread_print_name)
|
|
{
|
|
char buffer[16];
|
|
sprintf(buffer, "%d", loadInfo->getId());
|
|
thread_print_name = buffer;
|
|
}
|
|
|
|
u32 switch_count = loadInfo->getCount();
|
|
float cost_per_0x18 = loadInfo->getCost() / (float)_18;
|
|
|
|
u32 cost_int = (u32)(cost_per_0x18 * 100.0f);
|
|
u32 cost_float = (u32)(cost_per_0x18 * 1000.0f) % 10;
|
|
if (!console)
|
|
{
|
|
/*#if DEBUG
|
|
OSReport(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name, switch_count,
|
|
cost_int, cost_float);
|
|
#endif*/
|
|
}
|
|
else
|
|
{
|
|
console->print_f(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name,
|
|
switch_count, cost_int, cost_float);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
CW_FORCE_STRINGS(JKRThread_2, "JUTConsole.h", "console != 0", "bufSize > 0", "sEndMesgBuffer")
|
|
#endif
|
|
|
|
JKRTask::JKRTask(int msgCount, int threadPriority, u32 stackSize)
|
|
: JKRThread(stackSize, msgCount, threadPriority), mTaskLink(this), mTaskMsgQueue(nullptr)
|
|
{
|
|
// UNUSED FUNCTION
|
|
OSResumeThread(mThreadRecord);
|
|
}
|
|
|
|
JKRTask::~JKRTask() { sTaskList.remove(&mTaskLink); }
|
|
|
|
JKRTask *JKRTask::create(int reqCount, int threadPriority, u32 stackSize, JKRHeap *heap)
|
|
{
|
|
if (heap == nullptr)
|
|
{
|
|
heap = JKRHeap::sCurrentHeap;
|
|
}
|
|
JKRTask *task = new (heap, 0) JKRTask(reqCount, threadPriority, stackSize);
|
|
if (task == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
task->mRequest = new (heap, 0) Request[reqCount];
|
|
task->mRequestCnt = reqCount;
|
|
if (task->mRequest == nullptr)
|
|
{
|
|
delete task;
|
|
return nullptr;
|
|
}
|
|
for (int i = 0; i < reqCount; i++)
|
|
{
|
|
task->mRequest[i].mCb = nullptr;
|
|
}
|
|
sTaskList.append(&task->mTaskLink);
|
|
return task;
|
|
}
|
|
|
|
void *JKRTask::run()
|
|
{
|
|
Request *req;
|
|
OSInitFastCast();
|
|
while (true)
|
|
{
|
|
req = (Request *)waitMessageBlock();
|
|
if (req->mCb != nullptr)
|
|
{
|
|
req->mCb(req->mArg);
|
|
if (mTaskMsgQueue != nullptr)
|
|
{
|
|
OSSendMessage(mTaskMsgQueue, req->mMsg, OS_MESSAGE_NOBLOCK);
|
|
}
|
|
}
|
|
req->mCb = nullptr;
|
|
}
|
|
}
|
|
|
|
JKRTask::Request *JKRTask::searchBlank()
|
|
{
|
|
// UNUSED FUNCTION
|
|
for (int i = 0; i < (int)mRequestCnt; i++)
|
|
{
|
|
if (mRequest[i].mCb == nullptr)
|
|
{
|
|
return &mRequest[i];
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool JKRTask::request(RequestCallback callback, void *arg, void *msg)
|
|
{
|
|
Request *req = searchBlank();
|
|
if (req == nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
req->mCb = callback;
|
|
req->mArg = arg;
|
|
req->mMsg = msg;
|
|
bool sendResult = OSSendMessage(&mMessageQueue, req, OS_MESSAGE_NOBLOCK);
|
|
if (!sendResult)
|
|
{
|
|
req->mCb = nullptr;
|
|
}
|
|
return sendResult;
|
|
}
|