Reschedule on IO completion, drop the reschedule in time queries

The time queries rescheduled since 2013, so that a game spinning on the
clock would let a thread that a timing event had woken run (it fixed
audio in Crimson Gem Saga and Where Is My Heart?). In 2014 audio and
delay wakeups started rescheduling themselves, but IO completion never
did, and a movie reader thread in Driver 76 was only getting in through
the time queries. Now IO completion dispatches like any other wakeup.

The PSP doesn't dispatch in a time query, and doing so let a thread
that a terminate woke run too early. threads/threads/terminate now
passes.

Checked by booting 75 games against master: the same in all of them,
with Asphalt Urban GT2 getting further in the same time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-29 09:19:32 -06:00
1 parent 638da935ea
commit 436db85cf5
3 files changed
+6 -7

No files matched your search

+4
View File
@@ -474,6 +474,9 @@ static void __IoAsyncNotify(u64 userdata, int cyclesLate) {
if (f->closePending) {
__IoFreeFd(fd, error);
}
// Like any interrupt that wakes a thread, this dispatches right away, so a better
// priority waiter doesn't sit ready until something else happens to reschedule.
__KernelReSchedule("async io completed");
}
}
@@ -522,6 +525,7 @@ static void __IoSyncNotify(u64 userdata, int cyclesLate) {
HLEKernel::ResumeFromWait(threadID, WAITTYPE_IO, fd, result);
f->waitingSyncThreads.erase(std::remove(f->waitingSyncThreads.begin(), f->waitingSyncThreads.end(), threadID), f->waitingSyncThreads.end());
__KernelReSchedule("io completed");
}
static void __IoAsyncBeginCallback(SceUID threadID, SceUID prevCallbackId) {
-6
View File
@@ -74,7 +74,6 @@ int sceKernelGetSystemTime(u32 sysclockPtr)
}
VERBOSE_LOG(Log::sceKernel, "sceKernelGetSystemTime(out:%16llx)", t);
hleEatCycles(265);
hleReSchedule("system time");
return hleNoLog(0);
}
@@ -87,7 +86,6 @@ u32 sceKernelGetSystemTimeLow()
if (PSP_CoreParameter().compat.flags().KernelGetSystemTimeLowEatMoreCycles) {
hleEatCycles(70000);
}
hleReSchedule("system time");
return hleNoLog((u32)t);
}
@@ -96,7 +94,6 @@ u64 sceKernelGetSystemTimeWide()
u64 t = CoreTiming::GetGlobalTimeUsScaled();
VERBOSE_LOG(Log::sceKernel,"%i=sceKernelGetSystemTimeWide()",(u32)t);
hleEatCycles(250);
hleReSchedule("system time");
return hleNoLog(t);
}
@@ -153,7 +150,6 @@ u32 sceKernelLibcClock()
{
u32 retVal = (u32) CoreTiming::GetGlobalTimeUs();
hleEatCycles(330);
hleReSchedule("libc clock");
return hleLogDebug(Log::sceKernel, retVal);
}
@@ -169,7 +165,6 @@ u32 sceKernelLibcTime(u32 outPtr)
else if (outPtr != 0)
return 0;
hleReSchedule("libc time");
return hleLogDebug(Log::sceKernel, t);
}
@@ -185,7 +180,6 @@ u32 sceKernelLibcGettimeofday(u32 timeAddr, u32 tzAddr)
DEBUG_LOG(Log::sceKernel,"sceKernelLibcGettimeofday(%08x, %08x)", timeAddr, tzAddr);
hleEatCycles(1885);
hleReSchedule("libc timeofday");
return hleNoLog(0);
}
+2 -1
View File
@@ -405,6 +405,8 @@ tests_good = [
"threads/threads/stackfree",
"threads/threads/start",
"threads/threads/suspend",
"threads/threads/terminate",
"threads/threads/termsuspended",
"threads/threads/threadend",
"threads/threads/threadmanidlist",
"threads/threads/threadmanidtype",
@@ -599,7 +601,6 @@ tests_next = [
"threads/scheduling/dispatch",
"threads/scheduling/scheduling",
"threads/threads/create",
"threads/threads/terminate",
"threads/tls/memory",
"threads/vpl/create",
"umd/io/umd_io",