Skip to content

Commit

Permalink
Merge pull request #14073 from unknownbrackets/hle-delay
Browse files Browse the repository at this point in the history
Log errors when delaying or waiting an already waiting thread
  • Loading branch information
hrydgard committed Feb 15, 2021
2 parents eed70fc + f75cb9f commit e1d73b2
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 25 deletions.
32 changes: 17 additions & 15 deletions Core/HLE/HLE.cpp
Expand Up @@ -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;
}

Expand Down
27 changes: 17 additions & 10 deletions Core/HLE/sceKernelThread.cpp
Expand Up @@ -1210,7 +1210,15 @@ bool KernelIsThreadDormant(SceUID threadID) {
PSPThread *t = kernelObjects.Get<PSPThread>(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<PSPThread>(threadID, error);
if (t)
return (t->nt.status & (THREADSTATUS_WAITSUSPEND)) != 0;
return false;
}

u32 __KernelGetWaitValue(SceUID threadID, u32 &error) {
Expand Down Expand Up @@ -1518,39 +1526,38 @@ 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)));
thread->nt.numReleases++;
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)));
Expand Down
1 change: 1 addition & 0 deletions Core/HLE/sceKernelThread.h
Expand Up @@ -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);
Expand Down

0 comments on commit e1d73b2

Please sign in to comment.