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:
Unknown W. Brackets 2012-12-06 23:03:09 -08:00
parent 6fd71f5b27
commit 15c05dc08c
3 changed files with 64 additions and 26 deletions

View File

@ -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"},

View File

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

View File

@ -48,6 +48,7 @@ void sceKernelResumeThread();
void sceKernelWakeupThread();
void sceKernelCancelWakeupThread();
void sceKernelTerminateDeleteThread();
void sceKernelTerminateThread(u32 threadID);
void sceKernelWaitThreadEndCB();
void sceKernelGetThreadExitStatus();
void sceKernelGetThreadmanIdType();