From b9ae57467946053265520c071d1e83dd420f7f64 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 23:40:12 -0800 Subject: [PATCH 1/2] Thread: Log error when delaying a waiting thread. This will handle double delaying and delaying in general. --- Core/HLE/HLE.cpp | 32 +++++++++++++++++--------------- Core/HLE/sceKernelThread.cpp | 10 +++++++++- Core/HLE/sceKernelThread.h | 1 + 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index e57afafe66..4427c6bd6c 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -365,28 +365,30 @@ bool hleExecuteDebugBreak(const HLEFunction &func) return true; } -u32 hleDelayResult(u32 result, const char *reason, int usec) -{ - if (__KernelIsDispatchEnabled()) - { - CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, __KernelGetCurThread()); +u32 hleDelayResult(u32 result, const char *reason, int usec) { + if (!__KernelIsDispatchEnabled()) { + WARN_LOG(HLE, "%s: Dispatch disabled, not delaying HLE result (right thing to do?)", latestSyscall ? latestSyscall->name : "?"); + } else { + SceUID thread = __KernelGetCurThread(); + if (KernelIsThreadWaiting(thread)) + ERROR_LOG(HLE, "%s: Delaying a thread that's already waiting", latestSyscall ? latestSyscall->name : "?"); + CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, thread); __KernelWaitCurThread(WAITTYPE_HLEDELAY, 1, result, 0, false, reason); } - else - WARN_LOG(HLE, "Dispatch disabled, not delaying HLE result (right thing to do?)"); return result; } -u64 hleDelayResult(u64 result, const char *reason, int usec) -{ - if (__KernelIsDispatchEnabled()) - { - u64 param = (result & 0xFFFFFFFF00000000) | __KernelGetCurThread(); +u64 hleDelayResult(u64 result, const char *reason, int usec) { + if (!__KernelIsDispatchEnabled()) { + WARN_LOG(HLE, "%s: Dispatch disabled, not delaying HLE result (right thing to do?)", latestSyscall ? latestSyscall->name : "?"); + } else { + SceUID thread = __KernelGetCurThread(); + if (KernelIsThreadWaiting(thread)) + ERROR_LOG(HLE, "%s: Delaying a thread that's already waiting", latestSyscall ? latestSyscall->name : "?"); + u64 param = (result & 0xFFFFFFFF00000000) | thread; CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, param); - __KernelWaitCurThread(WAITTYPE_HLEDELAY, 1, (u32) result, 0, false, reason); + __KernelWaitCurThread(WAITTYPE_HLEDELAY, 1, (u32)result, 0, false, reason); } - else - WARN_LOG(HLE, "Dispatch disabled, not delaying HLE result (right thing to do?)"); return result; } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 92c5fee535..74eb260b3a 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1212,7 +1212,15 @@ bool KernelIsThreadDormant(SceUID threadID) { PSPThread *t = kernelObjects.Get(threadID, error); if (t) return (t->nt.status & (THREADSTATUS_DEAD | THREADSTATUS_DORMANT)) != 0; - return 0; + return false; +} + +bool KernelIsThreadWaiting(SceUID threadID) { + u32 error; + PSPThread *t = kernelObjects.Get(threadID, error); + if (t) + return (t->nt.status & (THREADSTATUS_WAITSUSPEND)) != 0; + return false; } u32 __KernelGetWaitValue(SceUID threadID, u32 &error) { diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 3df1d70fc0..068d9f178f 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -173,6 +173,7 @@ u32 __KernelGetCurThreadStack(); u32 __KernelGetCurThreadStackStart(); const char *__KernelGetThreadName(SceUID threadID); bool KernelIsThreadDormant(SceUID threadID); +bool KernelIsThreadWaiting(SceUID threadID); void __KernelSaveContext(PSPThreadContext *ctx, bool vfpuEnabled); void __KernelLoadContext(PSPThreadContext *ctx, bool vfpuEnabled); From f75cb9fbae36a3bb8851f2607a10b63708b20017 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Feb 2021 23:55:58 -0800 Subject: [PATCH 2/2] Thread: Log error waiting already waiting thread. --- Core/HLE/sceKernelThread.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 74eb260b3a..c1dc1eb23f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1528,16 +1528,16 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, u64 retval) } // makes the current thread wait for an event -void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr, bool processCallbacks, const char *reason) -{ - if (!dispatchEnabled) - { +void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr, bool processCallbacks, const char *reason) { + if (!dispatchEnabled) { WARN_LOG_REPORT(SCEKERNEL, "Ignoring wait, dispatching disabled... right thing to do?"); return; } PSPThread *thread = __GetCurrentThread(); _assert_(thread != nullptr); + if ((thread->nt.status & THREADSTATUS_WAIT) != 0) + WARN_LOG_REPORT(SCEKERNEL, "Waiting thread for %d that was already waiting for %d", type, thread->nt.waitType); thread->nt.waitID = waitID; thread->nt.waitType = type; __KernelChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->nt.status & THREADSTATUS_SUSPEND))); @@ -1545,22 +1545,21 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time thread->waitInfo.waitValue = waitValue; thread->waitInfo.timeoutPtr = timeoutPtr; - // TODO: time waster if (!reason) reason = "started wait"; hleReSchedule(processCallbacks, reason); } -void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr) -{ - if (!dispatchEnabled) - { +void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr) { + if (!dispatchEnabled) { WARN_LOG_REPORT(SCEKERNEL, "Ignoring wait, dispatching disabled... right thing to do?"); return; } PSPThread *thread = __GetCurrentThread(); + if ((thread->nt.status & THREADSTATUS_WAIT) != 0) + WARN_LOG_REPORT(SCEKERNEL, "Waiting thread for %d that was already waiting for %d", type, thread->nt.waitType); thread->nt.waitID = waitID; thread->nt.waitType = type; __KernelChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->nt.status & THREADSTATUS_SUSPEND)));