mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-01 21:56:17 +00:00
Implement sceKernelTerminateThread(), not fully.
It's mostly correct but needs some tests and TLC. This allows threads to be restarted.
This commit is contained in:
parent
6fd71f5b27
commit
15c05dc08c
@ -377,7 +377,7 @@ const HLEFunction ThreadManForUser[] =
|
||||
{0x82826f70,sceKernelSleepThreadCB,"sceKernelSleepThreadCB"},
|
||||
{0xF475845D,&WrapV_IUU<sceKernelStartThread>,"sceKernelStartThread"},
|
||||
{0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"},
|
||||
{0x616403ba,0,"sceKernelTerminateThread"},
|
||||
{0x616403ba,WrapV_U<sceKernelTerminateThread>,"sceKernelTerminateThread"},
|
||||
{0x383f7bcc,sceKernelTerminateDeleteThread,"sceKernelTerminateDeleteThread"},
|
||||
{0x840E8133,sceKernelWaitThreadEndCB,"sceKernelWaitThreadEndCB"},
|
||||
{0xd13bde95,sceKernelCheckThreadStack,"sceKernelCheckThreadStack"},
|
||||
|
@ -273,6 +273,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId);
|
||||
int g_inCbCount = 0;
|
||||
|
||||
Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr);
|
||||
void __KernelResetThread(Thread *t);
|
||||
void __KernelCancelWakeup(SceUID threadID);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -350,8 +351,8 @@ void __KernelThreadingInit()
|
||||
|
||||
// Create the two idle threads, as well. With the absolute minimal possible priority.
|
||||
// 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads...
|
||||
__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL);
|
||||
__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL);
|
||||
__KernelResetThread(__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
|
||||
__KernelResetThread(__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
|
||||
// These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below.
|
||||
|
||||
__KernelListenThreadEnd(__KernelCancelWakeup);
|
||||
@ -850,6 +851,25 @@ void ThreadContext::reset()
|
||||
lo = 0;
|
||||
}
|
||||
|
||||
void __KernelResetThread(Thread *t)
|
||||
{
|
||||
t->context.reset();
|
||||
t->context.hi = 0;
|
||||
t->context.lo = 0;
|
||||
t->context.pc = t->nt.entrypoint;
|
||||
|
||||
// TODO: Reset the priority?
|
||||
t->nt.waitType = WAITTYPE_NONE;
|
||||
t->nt.waitID = 0;
|
||||
memset(&t->waitInfo, 0, sizeof(t->waitInfo));
|
||||
|
||||
t->nt.exitStatus = 0;
|
||||
t->isProcessingCallbacks = false;
|
||||
|
||||
t->context.r[MIPS_REG_RA] = threadReturnHackAddr; //hack! TODO fix
|
||||
t->AllocateStack(t->nt.stackSize); // can change the stacksize!
|
||||
}
|
||||
|
||||
Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr)
|
||||
{
|
||||
Thread *t = new Thread;
|
||||
@ -857,39 +877,28 @@ Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32
|
||||
|
||||
threadqueue.push_back(t);
|
||||
|
||||
t->context.reset();
|
||||
|
||||
t->context.hi = 0;
|
||||
t->context.lo = 0;
|
||||
t->context.pc = entryPoint;
|
||||
memset(&t->nt, 0xCD, sizeof(t->nt));
|
||||
|
||||
t->nt.entrypoint = entryPoint;
|
||||
t->nt.nativeSize = sizeof(t->nt);
|
||||
t->nt.attr = attr;
|
||||
t->nt.initialPriority = t->nt.currentPriority = priority;
|
||||
t->nt.entrypoint = entryPoint;
|
||||
t->nt.nativeSize = sizeof(t->nt);
|
||||
t->nt.attr = attr;
|
||||
t->nt.initialPriority = t->nt.currentPriority = priority;
|
||||
t->nt.stackSize = stacksize;
|
||||
t->nt.status = THREADSTATUS_DORMANT;
|
||||
t->nt.waitType = WAITTYPE_NONE;
|
||||
t->nt.waitID = 0;
|
||||
memset(&t->waitInfo, 0, sizeof(t->waitInfo));
|
||||
t->nt.exitStatus = 0;
|
||||
|
||||
t->nt.numInterruptPreempts = 0;
|
||||
t->nt.numReleases = 0;
|
||||
t->nt.numThreadPreempts = 0;
|
||||
t->nt.runForClocks.low = 0;
|
||||
t->nt.runForClocks.hi = 0;
|
||||
t->nt.wakeupCount = 0;
|
||||
t->isProcessingCallbacks = false;
|
||||
if (moduleId)
|
||||
t->nt.gpreg = __KernelGetModuleGP(moduleId);
|
||||
else
|
||||
t->nt.gpreg = 0; // sceKernelStartThread will take care of this.
|
||||
if (moduleId)
|
||||
t->nt.gpreg = __KernelGetModuleGP(moduleId);
|
||||
else
|
||||
t->nt.gpreg = 0; // sceKernelStartThread will take care of this.
|
||||
t->moduleId = moduleId;
|
||||
|
||||
strncpy(t->nt.name, name, 32);
|
||||
t->context.r[MIPS_REG_RA] = threadReturnHackAddr; //hack! TODO fix
|
||||
t->AllocateStack(t->nt.stackSize); // can change the stacksize!
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -899,6 +908,7 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr
|
||||
//grab mips regs
|
||||
SceUID id;
|
||||
currentThread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr);
|
||||
__KernelResetThread(currentThread);
|
||||
currentThread->nt.status = THREADSTATUS_READY; // do not schedule
|
||||
|
||||
strcpy(currentThread->nt.name, "root");
|
||||
@ -948,6 +958,7 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr)
|
||||
|
||||
if (startThread->nt.status != THREADSTATUS_DORMANT)
|
||||
{
|
||||
printf("NOT DORMANT\n");
|
||||
//Not dormant, WTF?
|
||||
RETURN(ERROR_KERNEL_THREAD_IS_NOT_DORMANT);
|
||||
return;
|
||||
@ -956,6 +967,8 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr)
|
||||
INFO_LOG(HLE,"sceKernelStartThread(thread=%i, argSize=%i, argPtr= %08x )",
|
||||
threadToStartID,argSize,argBlockPtr);
|
||||
|
||||
__KernelResetThread(startThread);
|
||||
|
||||
startThread->nt.status = THREADSTATUS_READY;
|
||||
u32 sp = startThread->context.r[MIPS_REG_SP];
|
||||
if (argBlockPtr && argSize > 0)
|
||||
@ -1161,16 +1174,40 @@ void sceKernelTerminateDeleteThread()
|
||||
if (threadno != currentThread->GetUID())
|
||||
{
|
||||
//TODO: remove from threadqueue!
|
||||
INFO_LOG(HLE,"sceKernelTerminateDeleteThread(%i)",threadno);
|
||||
INFO_LOG(HLE, "sceKernelTerminateDeleteThread(%i)", threadno);
|
||||
RETURN(0); //kernelObjects.Destroy<Thread>(threadno));
|
||||
|
||||
//TODO: should we really reschedule here?
|
||||
//TODO: should we really reschedule here?
|
||||
if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadno))
|
||||
__KernelReSchedule("termdeletethread");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "Thread \"%s\" tries to delete itself! :(",currentThread->GetName());
|
||||
ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName());
|
||||
RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void sceKernelTerminateThread(u32 threadID)
|
||||
{
|
||||
if (threadID != currentThread->GetUID())
|
||||
{
|
||||
INFO_LOG(HLE, "sceKernelTerminateThread(%i)", threadID);
|
||||
RETURN(0);
|
||||
|
||||
u32 error;
|
||||
Thread *t = kernelObjects.Get<Thread>(threadID, error);
|
||||
if (t)
|
||||
{
|
||||
t->nt.status = THREADSTATUS_DORMANT;
|
||||
__KernelFireThreadEnd(t);
|
||||
__KernelTriggerWait(WAITTYPE_THREADEND, threadID);
|
||||
}
|
||||
// TODO: Return an error if it doesn't exist?
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName());
|
||||
RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ void sceKernelResumeThread();
|
||||
void sceKernelWakeupThread();
|
||||
void sceKernelCancelWakeupThread();
|
||||
void sceKernelTerminateDeleteThread();
|
||||
void sceKernelTerminateThread(u32 threadID);
|
||||
void sceKernelWaitThreadEndCB();
|
||||
void sceKernelGetThreadExitStatus();
|
||||
void sceKernelGetThreadmanIdType();
|
||||
|
Loading…
Reference in New Issue
Block a user