Remove threads from semaphores when they timeout.

This makes wait tests *almost* pass.  There's some timing
related issues left, though.
This commit is contained in:
Unknown W. Brackets 2012-11-18 19:57:08 -08:00
parent fd41851503
commit 619a9906de
4 changed files with 33 additions and 2 deletions

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "../../Core/CoreTiming.h"
@ -279,6 +280,15 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate)
if (timeoutPtr != 0)
Memory::Write_U32(0, timeoutPtr);
SceUID semaID = __KernelGetWaitID(threadID, error);
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());
s->ns.numWaitThreads--;
}
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
}
@ -301,6 +311,12 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
if (wantedCount > s->ns.maxCount || wantedCount <= 0)
{
RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT);
return;
}
// We need to set the return value BEFORE processing callbacks / etc.
RETURN(0);

View File

@ -402,7 +402,21 @@ u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error)
}
else
{
ERROR_LOG(HLE, "__KernelGetWaitValue ERROR: thread %i", threadID);
ERROR_LOG(HLE, "__KernelGetWaitTimeoutPtr ERROR: thread %i", threadID);
return 0;
}
}
SceUID __KernelGetWaitID(SceUID threadID, u32 &error)
{
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
{
return t->nt.waitID;
}
else
{
ERROR_LOG(HLE, "__KernelGetWaitID ERROR: thread %i", threadID);
return 0;
}
}

View File

@ -107,6 +107,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, int retval);
u32 __KernelGetWaitValue(SceUID threadID, u32 &error);
u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error);
SceUID __KernelGetWaitID(SceUID threadID, u32 &error);
void __KernelWaitCurThread(WaitType type, SceUID waitId, u32 waitValue, u32 timeoutPtr, bool processCallbacks);
void __KernelReSchedule(const char *reason = "no reason");
void __KernelReSchedule(bool doCallbacks, const char *reason);

View File

@ -34,7 +34,6 @@ tests_good = [
"threads/mutex/mutex",
"threads/mutex/delete/delete",
"threads/semaphores/semaphores",
"threads/semaphores/cancel/cancel",
"threads/semaphores/delete/delete",
"threads/semaphores/poll/poll",
"threads/semaphores/refer/refer",
@ -56,6 +55,7 @@ tests_next = [
"threads/mutex/try/try",
"threads/mutex/unlock/unlock",
"threads/scheduling/scheduling",
"threads/semaphores/cancel/cancel",
"threads/semaphores/create/create",
"threads/semaphores/priority/priority",
"threads/semaphores/wait/wait",