Files

409 lines
11 KiB
C++
Raw Permalink Normal View History

2023-05-07 01:28:37 +02:00
#include <stdio.h>
2023-02-20 13:06:11 +01:00
#include <dolphin/os.h>
2023-02-07 16:55:53 +01:00
#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"
2023-02-07 19:02:55 +01:00
// this file has some unused strings that need to be generated by ppcdis or fake functions
2023-02-07 16:55:53 +01:00
JSUList<JKRThread> JKRThread::sThreadList(false);
JSUList<JKRTask> JKRTask::sTaskList;
2024-06-24 16:55:25 +02:00
OSMessageQueue JKRTask::sEndMesgQueue;
2023-02-07 16:55:53 +01:00
2023-11-03 20:31:38 +01:00
JKRIdleThread *JKRIdleThread::sThread; // Unused
2023-11-03 18:08:54 +01:00
JKRThreadSwitch *JKRThreadSwitch::sManager;
2023-11-03 20:31:38 +01:00
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
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this)
{
JKRHeap *heap = JKRHeap::findFromRoot(this);
if (heap == nullptr)
{
2023-02-07 16:55:53 +01:00
heap = JKRHeap::getSystemHeap();
}
setCommon_heapSpecified(heap, stack_size, param_3);
setCommon_mesgQueue(mHeap, message_count);
}
2023-11-03 18:08:54 +01:00
JKRThread::JKRThread(JKRHeap *heap, u32 stack_size, int message_count, int param_4)
: mThreadListLink(this)
{
if (heap == nullptr)
{
2023-02-07 16:55:53 +01:00
heap = JKRHeap::getCurrentHeap();
}
setCommon_heapSpecified(heap, stack_size, param_4);
setCommon_mesgQueue(mHeap, message_count);
}
2023-11-03 18:08:54 +01:00
JKRThread::JKRThread(OSThread *thread, int message_count) : mThreadListLink(this)
{
2023-11-03 20:31:38 +01:00
mHeap = nullptr;
2023-02-07 16:55:53 +01:00
mThreadRecord = thread;
mStackSize = (u32)thread->stackEnd - (u32)thread->stackBase;
mStackMemory = thread->stackBase;
setCommon_mesgQueue(JKRHeap::getSystemHeap(), message_count);
}
JKRThread::~JKRThread()
{
2023-11-03 18:08:54 +01:00
sThreadList.remove(&mThreadListLink);
if (mHeap != nullptr)
{
if (!OSIsThreadTerminated(mThreadRecord))
{
OSDetachThread(mThreadRecord);
OSCancelThread(mThreadRecord);
}
2023-11-03 20:31:38 +01:00
JKRFreeToHeap(mHeap, mStackMemory);
JKRFreeToHeap(mHeap, mThreadRecord);
2023-11-03 18:08:54 +01:00
}
2023-11-03 20:31:38 +01:00
JKRFree(mMesgBuffer);
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
void JKRThread::setCommon_mesgQueue(JKRHeap *heap, int msgCount)
2023-02-07 16:55:53 +01:00
{
#line 128
2023-11-03 18:08:54 +01:00
mMessageCount = msgCount;
mMesgBuffer = (OSMessage *)JKRHeap::alloc(mMessageCount << 2, 0, heap);
JUT_ASSERT(mMesgBuffer);
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
OSInitMessageQueue(&mMessageQueue, mMesgBuffer, mMessageCount);
JKRThread::sThreadList.append(&mThreadListLink);
mCurrentHeap = nullptr;
mCurrentHeapError = nullptr;
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
BOOL JKRThread::setCommon_heapSpecified(JKRHeap *heap, u32 stackSize, int threadPriority)
2023-02-07 16:55:53 +01:00
{
#line 161
2023-11-03 18:08:54 +01:00
mHeap = heap;
mStackSize = stackSize & ~0x1F;
mStackMemory = JKRHeap::alloc(mStackSize, 0x20, mHeap);
JUT_ASSERT(mStackMemory);
2023-02-07 16:55:53 +01:00
2023-08-25 23:23:06 +02:00
#line 167
2023-11-03 18:08:54 +01:00
mThreadRecord = (OSThread *)JKRHeap::alloc(sizeof(OSThread), 0x20, mHeap);
JUT_ASSERT(mThreadRecord);
2023-11-03 18:08:54 +01:00
return OSCreateThread(mThreadRecord, &JKRThread::start, this, (void *)((u32)mStackMemory + mStackSize), mStackSize, threadPriority, 1);
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
void *JKRThread::start(void *thread) { return static_cast<JKRThread *>(thread)->run(); }
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
JKRThread *JKRThread::searchThread(OSThread *thread)
{
JSUList<JKRThread> &threadList = getList();
2023-02-07 16:55:53 +01:00
JSUListIterator<JKRThread> iterator;
2023-11-03 18:08:54 +01:00
for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator)
{
if (iterator->getThreadRecord() == thread)
{
2023-02-07 16:55:53 +01:00
return iterator.getObject();
}
}
return nullptr;
}
2023-08-18 19:42:08 +02:00
#ifdef DEBUG
CW_FORCE_STRINGS(JKRThread_1, "JKRThread:%x OSThread:%x Load:ID:%d (%s)\n", "sThread == 0")
2023-03-03 21:35:32 +01:00
#endif
2023-02-07 19:02:55 +01:00
2023-11-03 20:31:38 +01:00
JKRThreadSwitch::JKRThreadSwitch(JKRHeap *heap)
2023-02-07 19:02:55 +01:00
{
2023-11-03 20:31:38 +01:00
mHeap = heap;
2023-02-07 16:55:53 +01:00
OSSetSwitchThreadCallback(JKRThreadSwitch::callback);
2023-11-03 20:31:38 +01:00
_0C = 0;
_10 = 1;
_18 = 0;
2023-02-07 16:55:53 +01:00
sTotalCount = 0;
sTotalStart = 0;
2023-11-03 20:31:38 +01:00
mConsole = nullptr;
mThreadName = nullptr;
mSetNextHeap = true;
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
JKRThreadSwitch *JKRThreadSwitch::createManager(JKRHeap *heap)
{
#line 343
JUT_ASSERT(sManager == 0);
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
if (!heap)
{
2023-02-07 16:55:53 +01:00
heap = JKRGetCurrentHeap();
}
sManager = new (heap, 0) JKRThreadSwitch(heap);
return sManager;
}
2023-11-03 18:08:54 +01:00
JKRThread *JKRThreadSwitch::enter(JKRThread *thread, int id)
{
if (thread == nullptr)
{
2023-02-07 19:02:55 +01:00
return nullptr;
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
else
{
JKRThread *nextThread = JKRThread::searchThread(thread->getThreadRecord());
if (nextThread != nullptr)
2023-02-07 16:55:53 +01:00
thread = nextThread;
2023-11-03 18:08:54 +01:00
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
2023-02-07 16:55:53 +01:00
loadInfo->clear();
loadInfo->setValid(true);
loadInfo->setId(id);
}
return thread;
}
2023-11-03 18:08:54 +01:00
void JKRThreadSwitch::callback(OSThread *current, OSThread *next)
{
if (mUserPreCallback)
{
2023-02-07 16:55:53 +01:00
(*mUserPreCallback)(current, next);
}
sTotalCount = sTotalCount + 1;
2023-11-03 20:31:38 +01:00
JKRHeap *next_heap = nullptr;
2023-11-03 18:08:54 +01:00
JSUList<JKRThread> &threadList = JKRThread::getList();
2023-02-07 16:55:53 +01:00
JSUListIterator<JKRThread> iterator;
2023-11-03 18:08:54 +01:00
for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator)
{
JKRThread *thread = iterator.getObject();
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
if (thread->getThreadRecord() == current)
{
2023-02-07 16:55:53 +01:00
thread->setCurrentHeap(JKRHeap::getCurrentHeap());
2023-11-03 18:08:54 +01:00
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
if (loadInfo->isValid())
{
2023-02-07 16:55:53 +01:00
loadInfo->addCurrentCost();
}
}
2023-11-03 18:08:54 +01:00
if (thread->getThreadRecord() == next)
{
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
if (loadInfo->isValid())
{
2023-02-07 16:55:53 +01:00
loadInfo->setCurrentTime();
loadInfo->incCount();
}
2023-11-03 18:08:54 +01:00
if (sManager->mSetNextHeap)
{
2023-02-07 16:55:53 +01:00
next_heap = thread->getCurrentHeap();
2023-11-03 18:08:54 +01:00
if (!next_heap)
{
2023-02-07 16:55:53 +01:00
next_heap = JKRHeap::getCurrentHeap();
2023-11-03 18:08:54 +01:00
}
else if (JKRHeap::getRootHeap()->isSubHeap(next_heap))
{
2023-02-07 16:55:53 +01:00
continue;
2023-11-03 18:08:54 +01:00
}
else
{
switch (thread->getCurrentHeapError())
{
2023-02-07 16:55:53 +01:00
case 0:
2023-11-03 18:08:54 +01:00
#line 508
JUT_PANIC("JKRThreadSwitch: currentHeap destroyed.");
2023-02-07 16:55:53 +01:00
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;
}
}
}
}
}
2023-11-03 18:08:54 +01:00
if (next_heap)
{
2023-02-07 16:55:53 +01:00
next_heap->becomeCurrentHeap();
}
2023-11-03 18:08:54 +01:00
if (mUserPostCallback)
{
2023-02-07 16:55:53 +01:00
(*mUserPostCallback)(current, next);
}
}
2023-11-03 18:08:54 +01:00
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";
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
if (!console)
{
/*#if DEBUG
2023-11-03 20:31:38 +01:00
OSReport(print_0, getTotalCount(), (int)_18, _10);
2023-11-03 18:08:54 +01:00
OSReport(print_1);
#endif*/
}
else
{
2023-02-07 16:55:53 +01:00
console->clear();
2023-11-03 20:31:38 +01:00
console->print_f(print_0, getTotalCount(), (int)_18, _10);
2023-02-07 16:55:53 +01:00
console->print(print_1);
}
2023-11-03 20:31:38 +01:00
for (JSUListIterator<JKRThread> iterator = JKRThread::getList().getFirst(); iterator != JKRThread::getList().getEnd(); ++iterator)
2023-11-03 18:08:54 +01:00
{
JKRThread *thread = iterator.getObject();
JKRThread::TLoad *loadInfo = thread->getLoadInfo();
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
if (loadInfo->isValid())
{
2023-11-03 20:31:38 +01:00
char *thread_print_name = nullptr;
2023-11-03 18:08:54 +01:00
if (thread_name_list)
{
JKRThreadName_ *thread_name = thread_name_list;
for (; thread_name->name; thread_name++)
{
if (thread_name->id == loadInfo->getId())
{
2023-02-07 16:55:53 +01:00
thread_print_name = thread_name->name;
break;
}
}
}
2023-11-03 18:08:54 +01:00
if (!thread_print_name)
{
2023-02-07 16:55:53 +01:00
char buffer[16];
sprintf(buffer, "%d", loadInfo->getId());
thread_print_name = buffer;
}
u32 switch_count = loadInfo->getCount();
2023-11-03 20:31:38 +01:00
float cost_per_0x18 = loadInfo->getCost() / (float)_18;
2023-02-07 16:55:53 +01:00
u32 cost_int = (u32)(cost_per_0x18 * 100.0f);
u32 cost_float = (u32)(cost_per_0x18 * 1000.0f) % 10;
2023-11-03 18:08:54 +01:00
if (!console)
{
/*#if DEBUG
OSReport(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name, switch_count,
cost_int, cost_float);
#endif*/
}
else
{
2023-02-07 16:55:53 +01:00
console->print_f(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name,
switch_count, cost_int, cost_float);
}
}
}
}
2023-08-18 19:42:08 +02:00
#ifdef DEBUG
CW_FORCE_STRINGS(JKRThread_2, "JUTConsole.h", "console != 0", "bufSize > 0", "sEndMesgBuffer")
2023-03-03 21:35:32 +01:00
#endif
2023-02-07 19:02:55 +01:00
2023-02-07 16:55:53 +01:00
JKRTask::JKRTask(int msgCount, int threadPriority, u32 stackSize)
2023-11-03 20:31:38 +01:00
: JKRThread(stackSize, msgCount, threadPriority), mTaskLink(this), mTaskMsgQueue(nullptr)
2023-02-07 16:55:53 +01:00
{
2023-11-03 18:08:54 +01:00
// UNUSED FUNCTION
OSResumeThread(mThreadRecord);
2023-02-07 16:55:53 +01:00
}
2023-11-03 20:31:38 +01:00
JKRTask::~JKRTask() { sTaskList.remove(&mTaskLink); }
2023-02-07 16:55:53 +01:00
2023-11-03 18:08:54 +01:00
JKRTask *JKRTask::create(int reqCount, int threadPriority, u32 stackSize, JKRHeap *heap)
2023-02-07 16:55:53 +01:00
{
2023-11-03 18:08:54 +01:00
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;
}
2023-11-03 20:31:38 +01:00
sTaskList.append(&task->mTaskLink);
2023-11-03 18:08:54 +01:00
return task;
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
void *JKRTask::run()
2023-02-07 16:55:53 +01:00
{
2023-11-03 18:08:54 +01:00
Request *req;
2023-02-07 16:55:53 +01:00
OSInitFastCast();
2023-11-03 18:08:54 +01:00
while (true)
{
req = (Request *)waitMessageBlock();
if (req->mCb != nullptr)
{
req->mCb(req->mArg);
2023-11-03 20:31:38 +01:00
if (mTaskMsgQueue != nullptr)
2023-11-03 18:08:54 +01:00
{
2023-11-03 20:31:38 +01:00
OSSendMessage(mTaskMsgQueue, req->mMsg, OS_MESSAGE_NOBLOCK);
2023-11-03 18:08:54 +01:00
}
}
req->mCb = nullptr;
}
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
JKRTask::Request *JKRTask::searchBlank()
2023-02-07 16:55:53 +01:00
{
2023-11-03 18:08:54 +01:00
// UNUSED FUNCTION
for (int i = 0; i < (int)mRequestCnt; i++)
{
if (mRequest[i].mCb == nullptr)
{
return &mRequest[i];
}
}
return nullptr;
2023-02-07 16:55:53 +01:00
}
2023-11-03 18:08:54 +01:00
bool JKRTask::request(RequestCallback callback, void *arg, void *msg)
2023-02-07 16:55:53 +01:00
{
2023-11-03 18:08:54 +01:00
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;
2023-02-20 13:06:11 +01:00
}