Fix $v0 on wrong thread in semaphore funcs.

Need to RETURN() prior to switching threads or it will write to the
wrong thread, oops.
This commit is contained in:
Unknown W. Brackets committed 2012-11-12 07:24:40 -08:00
1 parent a0cacc7eb9
commit f37dd7fefe
4 files changed
+47 -34

No files matched your search

+4
View File
@@ -142,6 +142,10 @@ template<void func(int, u32, u32)> void WrapV_IUU() {
func(PARAM(0), PARAM(1), PARAM(2));
}
template<void func(int, int, u32)> void WrapV_IIU() {
func(PARAM(0), PARAM(1), PARAM(2));
}
template<void func(int, u32, u32, u32, u32)> void WrapV_IUUUU() {
func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
}
+5 -5
View File
@@ -327,14 +327,14 @@ const HLEFunction ThreadManForUser[] =
{0xCD203292,&WrapU_V<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag"},
{0xA66B0120,&WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus"},
{0x8FFDF9A2,&WrapI_IIU<sceKernelCancelSema>, "sceKernelCancelSema"},
{0x8FFDF9A2,&WrapV_IIU<sceKernelCancelSema>, "sceKernelCancelSema"},
{0xD6DA4BA1,sceKernelCreateSema, "sceKernelCreateSema"},
{0x28b6489c,&WrapI_I<sceKernelDeleteSema>, "sceKernelDeleteSema"},
{0x28b6489c,&WrapV_I<sceKernelDeleteSema>, "sceKernelDeleteSema"},
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
{0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"},
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema"},
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"},
{0x3F53E640,&WrapV_II<sceKernelSignalSema>, "sceKernelSignalSema"},
{0x4E3A1105,&WrapV_IIU<sceKernelWaitSema>, "sceKernelWaitSema"},
{0x6d212bac,&WrapV_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"},
{0x60107536,0,"sceKernelDeleteLwMutex"},
{0x19CFF145,0,"sceKernelCreateLwMutex"},
+33 -24
View File
@@ -77,7 +77,9 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason)
return wokeThreads;
}
int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
// int sceKernelCancelSema(SceUID id, int newCount, int *numWaitThreads);
// void because it changes threads.
void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
{
DEBUG_LOG(HLE,"sceKernelCancelSema(%i)", id);
@@ -97,16 +99,17 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
s->ns.currentCount = newCount;
s->ns.numWaitThreads = 0;
// We need to set the return value BEFORE rescheduling threads.
RETURN(0);
// TODO: Should this reschedule?
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL))
__KernelReSchedule("semaphore cancelled");
return 0;
}
else
{
ERROR_LOG(HLE, "sceKernelCancelSema : Trying to cancel invalid semaphore %i", id);
return error;
RETURN(error);
}
}
@@ -132,7 +135,8 @@ void sceKernelCreateSema()
}
//int sceKernelDeleteSema(SceUID semaid);
int sceKernelDeleteSema(SceUID id)
// void because it changes threads.
void sceKernelDeleteSema(SceUID id)
{
DEBUG_LOG(HLE,"sceKernelDeleteSema(%i)", id);
@@ -140,18 +144,18 @@ int sceKernelDeleteSema(SceUID id)
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
// TODO: Should this reschedule?
// threads/semaphore doesn't get final threads if not, but gets wrong result if so.
// Probably it should and there's a bug with the registers?
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE))
{
RETURN(kernelObjects.Destroy<Semaphore>(id));
__KernelReSchedule("semaphore deleted");
return kernelObjects.Destroy<Semaphore>(id);
}
else
RETURN(kernelObjects.Destroy<Semaphore>(id));
}
else
{
ERROR_LOG(HLE, "sceKernelDeleteSema : Trying to delete invalid semaphore %i", id);
return error;
RETURN(error);
}
}
@@ -174,7 +178,8 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
}
//int sceKernelSignalSema(SceUID semaid, int signal);
int sceKernelSignalSema(SceUID id, int signal)
// void because it changes threads.
void sceKernelSignalSema(SceUID id, int signal)
{
//TODO: check that this thing really works :)
u32 error;
@@ -188,7 +193,10 @@ int sceKernelSignalSema(SceUID id, int signal)
else
s->ns.currentCount += signal;
DEBUG_LOG(HLE,"sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount);
// We need to set the return value BEFORE processing other threads.
RETURN(0);
bool wokeThreads = false;
retry:
//TODO: check for threads to wake up - wake them
@@ -212,27 +220,28 @@ retry:
break;
}
}
// RETURN(0);
//pop the thread that were released from waiting
// I don't think we should reschedule here
//if (wokeThreads)
// __KernelReSchedule("semaphore signalled");
return 0;
}
else
{
ERROR_LOG(HLE, "sceKernelSignalSema : Trying to signal invalid semaphore %i", id);
return error;
RETURN(error;)
}
}
int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks)
void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks)
{
u32 error;
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
if (s)
{
// We need to set the return value BEFORE processing callbacks / etc.
RETURN(0);
if (s->ns.currentCount >= wantedCount) //TODO fix
s->ns.currentCount -= wantedCount;
else
@@ -244,30 +253,30 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *bad
if (processCallbacks)
__KernelCheckCallbacks();
}
return 0;
}
else
{
ERROR_LOG(HLE, badSemaMessage, id);
return error;
RETURN(error);
}
}
//int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout);
int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
// void because it changes threads.
void 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);
__KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false);
}
//int sceKernelWaitSemaCB(SceUID semaid, int signal, SceUInt *timeout);
int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr)
// void because it changes threads.
void sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr)
{
DEBUG_LOG(HLE,"sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr);
return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true);
__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
+5 -5
View File
@@ -17,11 +17,11 @@
#pragma once
int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr);
void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr);
void sceKernelCreateSema();
int sceKernelDeleteSema(SceUID id);
void sceKernelDeleteSema(SceUID id);
int sceKernelPollSema(SceUID id, int wantedCount);
int sceKernelReferSemaStatus(SceUID id, u32 infoPtr);
int sceKernelSignalSema(SceUID id, int signal);
int sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr);
int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr);
void sceKernelSignalSema(SceUID id, int signal);
void sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr);
void sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr);