Cleanup sceKernel semaphore funcs.

Remove some duplication of code so it's cleaner.
This commit is contained in:
Unknown W. Brackets 2012-11-11 18:54:06 -08:00
parent a69fd56573
commit b58032039b

View file

@ -57,6 +57,26 @@ struct Semaphore : public KernelObject
std::vector<SceUID> waitingThreads;
};
// Resume all waiting threads (for delete / cancel.)
// Returns true if it woke any threads.
bool __KernelClearSemaThreads(Semaphore *s, int reason)
{
bool wokeThreads = false;
std::vector<SceUID>::iterator iter;
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
{
SceUID threadID = *iter;
// TODO: Set returnValue = reason?
__KernelResumeThreadFromWait(threadID);
wokeThreads = true;
}
s->waitingThreads.empty();
return wokeThreads;
}
int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
{
DEBUG_LOG(HLE,"sceKernelCancelSema(%i)", id);
@ -77,20 +97,8 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
s->ns.currentCount = newCount;
s->ns.numWaitThreads = 0;
bool wokeThreads = false;
std::vector<SceUID>::iterator iter;
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
{
SceUID threadID = *iter;
// TODO: Set SCE_KERNEL_ERROR_WAIT_CANCEL returnValue?
__KernelResumeThreadFromWait(threadID);
wokeThreads = true;
}
s->waitingThreads.empty();
if (wokeThreads)
// TODO: Should this reschedule?
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL))
__KernelReSchedule("semaphore cancelled");
return 0;
@ -132,21 +140,8 @@ int sceKernelDeleteSema(SceUID id)
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
bool wokeThreads = false;
std::vector<SceUID>::iterator iter;
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
{
SceUID threadID = *iter;
// TODO: Set SCE_KERNEL_ERROR_WAIT_DELETE returnValue?
__KernelResumeThreadFromWait(threadID);
wokeThreads = true;
}
s->waitingThreads.empty();
// TODO: Should this reschedule? threads/semaphores fails if it doesn't.
if (wokeThreads)
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE))
__KernelReSchedule("semaphore deleted");
return kernelObjects.Destroy<Semaphore>(id);
@ -230,32 +225,39 @@ retry:
}
}
//int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout);
int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks)
{
u32 error;
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
DEBUG_LOG(HLE,"sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr);
if (s->ns.currentCount >= wantedCount) //TODO fix
{
s->ns.currentCount -= wantedCount;
return 0;
}
else
{
s->ns.numWaitThreads++;
s->waitingThreads.push_back(__KernelGetCurThread());
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, false);
return 0;
// TODO: timeoutPtr?
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, processCallbacks);
if (processCallbacks)
__KernelCheckCallbacks();
}
return 0;
}
else
{
ERROR_LOG(HLE, "sceKernelWaitSema : Trying to wait for invalid semaphore %i", id);
ERROR_LOG(HLE, badSemaMessage, id);
return error;
}
}
//int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout);
int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
{
DEBUG_LOG(HLE,"sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr);
return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false);
}
//int sceKernelWaitSemaCB(SceUID semaid, int signal, SceUInt *timeout);
@ -263,56 +265,30 @@ int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr)
{
DEBUG_LOG(HLE,"sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr);
u32 error;
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
DEBUG_LOG(HLE,"CurrentCount: %i, Signal: %i", s->ns.currentCount, wantedCount);
if (s->ns.currentCount >= wantedCount) //TODO fix
{
DEBUG_LOG(HLE,"Subtracting");
s->ns.currentCount -= wantedCount;
}
else
{
s->ns.numWaitThreads++;
s->waitingThreads.push_back(__KernelGetCurThread());
// TODO: timeoutPtr?
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, true);
__KernelCheckCallbacks();
return 0;
}
DEBUG_LOG(HLE,"After: CurrentCount: %i, Signal: %i", s->ns.currentCount, wantedCount);
return 0;
}
else
{
ERROR_LOG(HLE,"sceKernelWaitSemaCB - Bad semaphore");
return error;
}
return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true);
}
// Should be same as WaitSema but without the wait, instead returning SCE_KERNEL_ERROR_SEMA_ZERO
int sceKernelPollSema(SceUID id, int wantedCount)
{
DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount);
u32 error;
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount);
if (s->ns.currentCount >= wantedCount) //TODO fix
{
s->ns.currentCount -= wantedCount;
return 0;
}
else
{
return SCE_KERNEL_ERROR_SEMA_ZERO;
}
return 0;
}
else
{
ERROR_LOG(HLE, "sceKernelPollSema : Trying to poll invalid semaphore %i", id);
ERROR_LOG(HLE, "sceKernelPollSema: Trying to poll invalid semaphore %i", id);
return error;
}
}