mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-03 15:42:32 +00:00
Consider threads still waiting until they wake.
This seems to match the actual behavior of timeouts much better.
This commit is contained in:
parent
48c5efd0c2
commit
998104e2eb
@ -215,6 +215,10 @@ void sceKernelDeleteMutex(SceUID id)
|
||||
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != id)
|
||||
continue;
|
||||
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
if (timeoutPtr != 0 && mutexWaitTimer != 0)
|
||||
@ -288,9 +292,17 @@ bool __KernelUnlockMutex(Mutex *mutex, u32 &error)
|
||||
// TODO: PSP_MUTEX_ATTR_PRIORITY
|
||||
bool wokeThreads = false;
|
||||
std::vector<SceUID>::iterator iter, end;
|
||||
retry:
|
||||
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != mutex->GetUID())
|
||||
{
|
||||
mutex->waitingThreads.erase(iter);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
int wVal = (int)__KernelGetWaitValue(threadID, error);
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
@ -325,14 +337,6 @@ void __KernelMutexTimeout(u64 userdata, int cyclesLate)
|
||||
if (timeoutPtr != 0)
|
||||
Memory::Write_U32(0, timeoutPtr);
|
||||
|
||||
SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error);
|
||||
Mutex *mutex = kernelObjects.Get<Mutex>(mutexID, error);
|
||||
if (mutex)
|
||||
{
|
||||
// This thread isn't waiting anymore.
|
||||
mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end());
|
||||
}
|
||||
|
||||
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
@ -543,6 +547,10 @@ void sceKernelDeleteLwMutex(u32 workareaPtr)
|
||||
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != mutex->GetUID())
|
||||
continue;
|
||||
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
if (timeoutPtr != 0 && lwMutexWaitTimer != 0)
|
||||
@ -631,9 +639,17 @@ bool __KernelUnlockLwMutex(NativeLwMutexWorkarea &workarea, u32 &error)
|
||||
// TODO: PSP_MUTEX_ATTR_PRIORITY
|
||||
bool wokeThreads = false;
|
||||
std::vector<SceUID>::iterator iter, end;
|
||||
retry:
|
||||
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != mutex->GetUID())
|
||||
{
|
||||
mutex->waitingThreads.erase(iter);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
int wVal = (int)__KernelGetWaitValue(threadID, error);
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
@ -669,14 +685,6 @@ void __KernelLwMutexTimeout(u64 userdata, int cyclesLate)
|
||||
if (timeoutPtr != 0)
|
||||
Memory::Write_U32(0, timeoutPtr);
|
||||
|
||||
SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error);
|
||||
LwMutex *mutex = kernelObjects.Get<LwMutex>(mutexID, error);
|
||||
if (mutex)
|
||||
{
|
||||
// This thread isn't waiting anymore.
|
||||
mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end());
|
||||
}
|
||||
|
||||
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,13 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason)
|
||||
std::vector<SceUID>::iterator iter;
|
||||
for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
|
||||
u32 error;
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != s->GetUID())
|
||||
continue;
|
||||
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
if (timeoutPtr != 0 && semaWaitTimer != 0)
|
||||
{
|
||||
@ -242,6 +246,13 @@ retry:
|
||||
for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error);
|
||||
// The waitID may be different after a timeout.
|
||||
if (waitID != s->GetUID())
|
||||
{
|
||||
s->waitingThreads.erase(iter);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
int wVal = (int)__KernelGetWaitValue(threadID, error);
|
||||
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
|
||||
@ -288,8 +299,7 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate)
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(semaID, error);
|
||||
if (s)
|
||||
{
|
||||
// This thread isn't waiting anymore.
|
||||
s->waitingThreads.erase(std::remove(s->waitingThreads.begin(), s->waitingThreads.end(), threadID), s->waitingThreads.end());
|
||||
// This thread isn't waiting anymore, but we'll remove it from waitingThreads later.
|
||||
s->ns.numWaitThreads--;
|
||||
}
|
||||
|
||||
|
@ -1545,6 +1545,10 @@ void __KernelSwitchContext(Thread *target, const char *reason)
|
||||
__KernelLoadContext(¤tThread->context);
|
||||
DEBUG_LOG(HLE,"Context loaded (%s): %i - %s - pc: %08x", reason, currentThread->GetUID(), currentThread->GetName(), currentMIPS->pc);
|
||||
|
||||
// No longer waiting.
|
||||
currentThread->nt.waitType = WAITTYPE_NONE;
|
||||
currentThread->nt.waitID = 0;
|
||||
|
||||
__KernelExecutePendingMipsCalls();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user