Mutexes and semaphores don't always reschedule.

It's just the normal rescheduling happening.  Previous tests weren't
correct.

Also some minor cleanup.
This commit is contained in:
Unknown W. Brackets 2012-11-26 00:41:55 -08:00
parent 1189da826c
commit 3ab41e515d
2 changed files with 35 additions and 48 deletions

View File

@ -15,8 +15,6 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// UNFINISHED
#include <algorithm>
#include <map>
#include "HLE.h"
@ -203,8 +201,6 @@ void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 opti
WARN_LOG(HLE,"sceKernelCreateMutex(%s) unsupported options parameter.", name);
RETURN(id);
__KernelReSchedule("mutex created");
}
void sceKernelDeleteMutex(SceUID id)
@ -214,6 +210,7 @@ void sceKernelDeleteMutex(SceUID id)
Mutex *mutex = kernelObjects.Get<Mutex>(id, error);
if (mutex)
{
bool wokeThreads = false;
std::vector<SceUID>::iterator iter, end;
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
{
@ -228,13 +225,16 @@ void sceKernelDeleteMutex(SceUID id)
}
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE);
wokeThreads = true;
}
if (mutex->nm.lockThread != -1)
__KernelMutexEraseLock(mutex);
mutex->waitingThreads.empty();
mutex->waitingThreads.clear();
RETURN(kernelObjects.Destroy<Mutex>(id));
__KernelReSchedule("mutex deleted");
if (wokeThreads)
__KernelReSchedule("mutex deleted");
}
else
RETURN(error);
@ -386,7 +386,6 @@ void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
if (__KernelLockMutex(mutex, count, error))
{
RETURN(0);
__KernelReSchedule("mutex locked");
}
else if (error)
RETURN(error);
@ -395,6 +394,7 @@ void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
mutex->waitingThreads.push_back(__KernelGetCurThread());
__KernelWaitMutex(mutex, timeoutPtr);
__KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, false);
__KernelReSchedule("mutex locked");
}
}
@ -409,7 +409,6 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr)
if (__KernelLockMutex(mutex, count, error))
{
RETURN(0);
__KernelReSchedule("mutex locked");
}
else if (error)
RETURN(error);
@ -419,9 +418,8 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr)
__KernelWaitMutex(mutex, timeoutPtr);
__KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, true);
__KernelCheckCallbacks();
__KernelReSchedule("mutex locked");
}
__KernelReSchedule("mutex locked");
}
// int sceKernelTryLockMutex(SceUID id, int count)
@ -433,10 +431,7 @@ void sceKernelTryLockMutex(SceUID id, int count)
Mutex *mutex = kernelObjects.Get<Mutex>(id, error);
if (__KernelLockMutex(mutex, count, error))
{
RETURN(0);
__KernelReSchedule("mutex trylocked");
}
else if (error)
RETURN(error);
else
@ -474,8 +469,8 @@ void sceKernelUnlockMutex(SceUID id, int count)
if (mutex->nm.lockLevel == 0)
{
__KernelUnlockMutex(mutex, error);
__KernelReSchedule("mutex unlocked");
if (__KernelUnlockMutex(mutex, error))
__KernelReSchedule("mutex locked");
}
}
@ -524,8 +519,6 @@ void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int ini
WARN_LOG(HLE,"sceKernelCreateLwMutex(%s) unsupported options parameter.", name);
RETURN(0);
__KernelReSchedule("lwmutex created");
}
void sceKernelDeleteLwMutex(u32 workareaPtr)
@ -545,6 +538,7 @@ void sceKernelDeleteLwMutex(u32 workareaPtr)
LwMutex *mutex = kernelObjects.Get<LwMutex>(workarea.uid, error);
if (mutex)
{
bool wokeThreads = false;
std::vector<SceUID>::iterator iter, end;
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
{
@ -559,14 +553,16 @@ void sceKernelDeleteLwMutex(u32 workareaPtr)
}
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE);
wokeThreads = true;
}
mutex->waitingThreads.empty();
mutex->waitingThreads.clear();
RETURN(kernelObjects.Destroy<LwMutex>(workarea.uid));
workarea.clear();
Memory::WriteStruct(workareaPtr, &workarea);
__KernelReSchedule("mutex deleted");
if (wokeThreads)
__KernelReSchedule("lwmutex deleted");
}
else
RETURN(error);
@ -706,7 +702,6 @@ void sceKernelTryLockLwMutex(u32 workareaPtr, int count)
{
Memory::WriteStruct(workareaPtr, &workarea);
RETURN(0);
__KernelReSchedule("lwmutex trylocked");
}
else if (error)
RETURN(PSP_MUTEX_ERROR_TRYLOCK_FAILED);
@ -726,7 +721,6 @@ void sceKernelTryLockLwMutex_600(u32 workareaPtr, int count)
{
Memory::WriteStruct(workareaPtr, &workarea);
RETURN(0);
__KernelReSchedule("lwmutex trylocked");
}
else if (error)
RETURN(error);
@ -746,7 +740,6 @@ void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr)
{
Memory::WriteStruct(workareaPtr, &workarea);
RETURN(0);
__KernelReSchedule("lwmutex locked");
}
else if (error)
RETURN(error);
@ -758,6 +751,7 @@ void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr)
mutex->waitingThreads.push_back(__KernelGetCurThread());
__KernelWaitLwMutex(mutex, timeoutPtr);
__KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, false);
__KernelReSchedule("lwmutex locked");
}
else
RETURN(error);
@ -776,7 +770,6 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr)
{
Memory::WriteStruct(workareaPtr, &workarea);
RETURN(0);
__KernelReSchedule("lwmutex locked");
}
else if (error)
RETURN(error);
@ -789,6 +782,7 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr)
__KernelWaitLwMutex(mutex, timeoutPtr);
__KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, true);
__KernelCheckCallbacks();
__KernelReSchedule("lwmutex locked");
}
else
RETURN(error);
@ -825,9 +819,9 @@ void sceKernelUnlockLwMutex(u32 workareaPtr, int count)
if (workarea.lockLevel == 0)
{
__KernelUnlockLwMutex(workarea, error);
if (__KernelUnlockLwMutex(workarea, error))
__KernelReSchedule("lwmutex unlocked");
Memory::WriteStruct(workareaPtr, &workarea);
__KernelReSchedule("lwmutex unlocked");
}
else
Memory::WriteStruct(workareaPtr, &workarea);

View File

@ -78,7 +78,7 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason)
// TODO: PSP_SEMA_ATTR_PRIORITY
std::vector<SceUID>::iterator iter;
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter)
{
SceUID threadID = *iter;
@ -94,7 +94,7 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason)
__KernelResumeThreadFromWait(threadID, reason);
wokeThreads = true;
}
s->waitingThreads.empty();
s->waitingThreads.clear();
return wokeThreads;
}
@ -129,8 +129,8 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
// We need to set the return value BEFORE rescheduling threads.
RETURN(0);
__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL);
__KernelReSchedule("semaphore cancelled");
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL))
__KernelReSchedule("semaphore canceled");
}
else
{
@ -170,8 +170,6 @@ void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u3
WARN_LOG(HLE,"sceKernelCreateSema(%s) unsupported options parameter.", name);
RETURN(id);
__KernelReSchedule("semaphore created");
}
//int sceKernelDeleteSema(SceUID semaid);
@ -184,9 +182,11 @@ void sceKernelDeleteSema(SceUID id)
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE);
bool wokeThreads = __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE);
RETURN(kernelObjects.Destroy<Semaphore>(id));
__KernelReSchedule("semaphore deleted");
if (wokeThreads)
__KernelReSchedule("semaphore deleted");
}
else
{
@ -206,7 +206,6 @@ void sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, infoPtr);
Memory::WriteStruct(infoPtr, &s->ns);
RETURN(0);
__KernelReSchedule("semaphore refer status");
}
else
{
@ -219,7 +218,6 @@ void sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
// void because it changes threads.
void sceKernelSignalSema(SceUID id, int signal)
{
//TODO: check that this thing really works :)
u32 error;
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
@ -237,11 +235,11 @@ void sceKernelSignalSema(SceUID id, int signal)
// We need to set the return value BEFORE processing other threads.
RETURN(0);
bool wokeThreads = false;
retry:
// TODO: PSP_SEMA_ATTR_PRIORITY
bool wokeThreads = false;
std::vector<SceUID>::iterator iter;
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
retry:
for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter)
{
SceUID threadID = *iter;
@ -261,17 +259,14 @@ retry:
}
__KernelResumeThreadFromWait(threadID, 0);
wokeThreads = true;
s->waitingThreads.erase(iter);
wokeThreads = true;
goto retry;
}
else
{
break;
}
}
__KernelReSchedule("semaphore signalled");
if (wokeThreads)
__KernelReSchedule("semaphore signaled");
}
else
{
@ -336,9 +331,9 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr, processCallbacks);
if (processCallbacks)
__KernelCheckCallbacks();
}
__KernelReSchedule("semaphore waited");
__KernelReSchedule("semaphore waited");
}
}
else
{
@ -387,8 +382,6 @@ void sceKernelPollSema(SceUID id, int wantedCount)
}
else
RETURN(SCE_KERNEL_ERROR_SEMA_ZERO);
__KernelReSchedule("semaphore polled");
}
else
{