Files
2024-06-24 16:55:25 +02:00

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;
}