diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 0822338151..7371906bb8 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -692,14 +692,14 @@ const HLEFunction ThreadManForUser[] = {0xFFC36A14,WrapU_UU,"sceKernelReferThreadRunStatus"}, {0x17c1684e,WrapU_UU,"sceKernelReferThreadStatus"}, {0x2C34E053,WrapI_I,"sceKernelReleaseWaitThread"}, - {0x75156e8f,sceKernelResumeThread,"sceKernelResumeThread"}, + {0x75156e8f,WrapI_I,"sceKernelResumeThread"}, {0x3ad58b8c,&WrapU_V,"sceKernelSuspendDispatchThread"}, {0x27e22ec2,&WrapU_U,"sceKernelResumeDispatchThread"}, {0x912354a7,&WrapI_I,"sceKernelRotateThreadReadyQueue"}, {0x9ACE131E,WrapI_V,"sceKernelSleepThread"}, {0x82826f70,WrapI_V,"sceKernelSleepThreadCB"}, {0xF475845D,&WrapI_IIU,"sceKernelStartThread"}, - {0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"}, + {0x9944f31f,WrapI_I,"sceKernelSuspendThread"}, {0x616403ba,WrapI_I,"sceKernelTerminateThread"}, {0x383f7bcc,WrapI_I,"sceKernelTerminateDeleteThread"}, {0x840E8133,WrapI_IU,"sceKernelWaitThreadEndCB"}, diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 2711f67daf..d17080c679 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2484,16 +2484,60 @@ int sceKernelReleaseWaitThread(SceUID threadID) } } -void sceKernelSuspendThread() +int sceKernelSuspendThread(SceUID threadID) { - WARN_LOG_REPORT(HLE,"UNIMPL sceKernelSuspendThread"); - RETURN(0); + u32 error; + Thread *t = kernelObjects.Get(threadID, error); + if (t) + { + if (t->isStopped()) + { + ERROR_LOG(HLE, "sceKernelSuspendThread(%d): thread not running", threadID); + return SCE_KERNEL_ERROR_DORMANT; + } + if (t->isSuspended()) + { + ERROR_LOG(HLE, "sceKernelSuspendThread(%d): thread already suspended", threadID); + return SCE_KERNEL_ERROR_SUSPEND; + } + + WARN_LOG(HLE, "sceKernelSuspendThread(%d)", threadID); + if (t->isReady()) + __KernelChangeReadyState(t, threadID, false); + t->nt.status = (t->nt.status & ~THREADSTATUS_READY) | THREADSTATUS_SUSPEND; + return 0; + } + else + { + ERROR_LOG(HLE, "sceKernelSuspendThread(%d): bad thread", threadID); + return error; + } } -void sceKernelResumeThread() +int sceKernelResumeThread(SceUID threadID) { - WARN_LOG_REPORT(HLE,"UNIMPL sceKernelResumeThread"); - RETURN(0); + u32 error; + Thread *t = kernelObjects.Get(threadID, error); + if (t) + { + if (!t->isSuspended()) + { + ERROR_LOG(HLE, "sceKernelSuspendThread(%d): thread not suspended", threadID); + return SCE_KERNEL_ERROR_NOT_SUSPEND; + } + WARN_LOG(HLE, "sceKernelResumeThread(%d)", threadID); + t->nt.status &= ~THREADSTATUS_SUSPEND; + + // If it was dormant, waiting, etc. before we don't flip it's ready state. + if (t->nt.status == 0) + __KernelChangeReadyState(t, threadID, true); + return 0; + } + else + { + ERROR_LOG(HLE, "sceKernelResumeThread(%d): bad thread", threadID); + return error; + } } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index fa3b12740b..cccfe04ea1 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -47,8 +47,8 @@ int sceKernelReleaseWaitThread(SceUID threadID); void sceKernelChangeCurrentThreadAttr(); int sceKernelRotateThreadReadyQueue(int priority); int sceKernelCheckThreadStack(); -void sceKernelSuspendThread(); -void sceKernelResumeThread(); +int sceKernelSuspendThread(SceUID threadID); +int sceKernelResumeThread(SceUID threadID); int sceKernelWakeupThread(SceUID threadID); int sceKernelCancelWakeupThread(SceUID threadID); int sceKernelSleepThread();