From f9fc1af5c8a0d7b207721a0c5035223e738ed3cc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Mar 2013 14:11:53 -0800 Subject: [PATCH 1/2] Improve perf of sceKernelCheckCallback(). Some games seem to call this a lot. --- Core/HLE/sceKernelThread.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 6141993d69..e690f803b5 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2696,6 +2696,14 @@ bool __KernelCheckCallbacks() { bool __KernelForceCallbacks() { + // Let's not check every thread all the time, callbacks are fairly uncommon. + if (readyCallbacksCount == 0) { + return false; + } + if (readyCallbacksCount < 0) { + ERROR_LOG(HLE, "readyCallbacksCount became negative: %i", readyCallbacksCount); + } + Thread *curThread = __GetCurrentThread(); bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread, true); From 6b7ff47617a7b20f8bb4e1dd2896704d32d5977e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Mar 2013 14:21:21 -0800 Subject: [PATCH 2/2] Improve perf of __KernelExecutePendingMipsCalls(). This was using ~3% in many games with fast forward. It was all the RTL type lookup, so avoiding it is an easy win. --- Core/HLE/sceKernelThread.cpp | 13 +++++++------ Core/HLE/sceKernelThread.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index e690f803b5..9a1b144405 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2383,7 +2383,7 @@ void __KernelSwitchContext(Thread *target, const char *reason) target->nt.waitType = WAITTYPE_NONE; target->nt.waitID = 0; - __KernelExecutePendingMipsCalls(true); + __KernelExecutePendingMipsCalls(target, true); } void __KernelChangeThreadState(Thread *thread, ThreadStatus newStatus) { @@ -2552,7 +2552,7 @@ void __KernelReturnFromMipsCall() currentCallbackThreadID = 0; // yeah! back in the real world, let's keep going. Should we process more callbacks? - if (!__KernelExecutePendingMipsCalls(call->reschedAfter)) + if (!__KernelExecutePendingMipsCalls(cur, call->reschedAfter)) { // Sometimes, we want to stay on the thread. int threadReady = cur->nt.status & (THREADSTATUS_READY | THREADSTATUS_RUNNING); @@ -2563,9 +2563,10 @@ void __KernelReturnFromMipsCall() delete call; } -bool __KernelExecutePendingMipsCalls(bool reschedAfter) +// First arg must be current thread, passed to avoid perf cost of a lookup. +bool __KernelExecutePendingMipsCalls(Thread *thread, bool reschedAfter) { - Thread *thread = __GetCurrentThread(); + _dbg_assert_msg_(HLE, thread->GetUID() == __KernelGetCurThread(), "__KernelExecutePendingMipsCalls() should be called only with the current thread."); if (thread->pendingMipsCalls.empty()) { // Nothing to do @@ -2690,7 +2691,7 @@ bool __KernelCheckCallbacks() { // } while (processed && currentThread == __KernelGetCurThread()); if (processed) - return __KernelExecutePendingMipsCalls(true); + return __KernelExecutePendingMipsCalls(__GetCurrentThread(), true); return processed; } @@ -2708,7 +2709,7 @@ bool __KernelForceCallbacks() bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread, true); if (callbacksProcessed) - __KernelExecutePendingMipsCalls(false); + __KernelExecutePendingMipsCalls(curThread, false); return callbacksProcessed; } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index c2fd01e76e..fd0039c499 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -194,7 +194,7 @@ bool __KernelCheckCallbacks(); bool __KernelForceCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); -bool __KernelExecutePendingMipsCalls(bool reschedAfter); +bool __KernelExecutePendingMipsCalls(Thread *currentThread, bool reschedAfter); void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg); // Switch to an idle / non-user thread, if not already on one.