diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index d1d783b288..3544c9a171 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -377,7 +377,7 @@ const HLEFunction ThreadManForUser[] = {0x82826f70,sceKernelSleepThreadCB,"sceKernelSleepThreadCB"}, {0xF475845D,&WrapV_IUU,"sceKernelStartThread"}, {0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"}, - {0x616403ba,0,"sceKernelTerminateThread"}, + {0x616403ba,WrapV_U,"sceKernelTerminateThread"}, {0x383f7bcc,sceKernelTerminateDeleteThread,"sceKernelTerminateDeleteThread"}, {0x840E8133,sceKernelWaitThreadEndCB,"sceKernelWaitThreadEndCB"}, {0xd13bde95,sceKernelCheckThreadStack,"sceKernelCheckThreadStack"}, diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 97400b75ae..387bef79cf 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -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(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(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); } } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 8a649b6557..3782ccef33 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -48,6 +48,7 @@ void sceKernelResumeThread(); void sceKernelWakeupThread(); void sceKernelCancelWakeupThread(); void sceKernelTerminateDeleteThread(); +void sceKernelTerminateThread(u32 threadID); void sceKernelWaitThreadEndCB(); void sceKernelGetThreadExitStatus(); void sceKernelGetThreadmanIdType();