diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index b5d2d7cfb0..423ad49792 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -118,11 +118,6 @@ template void WrapI_CUUU() { RETURN(retval); } -template void WrapI_CUIIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - template void WrapU_CU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); RETURN((u32)retval); @@ -163,6 +158,10 @@ template void WrapV_UUUU() { func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); } +template void WrapV_CUIIU() { + func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); +} + template void WrapU_UUUU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 023ea449a5..c466ce63ad 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -328,10 +328,10 @@ const HLEFunction ThreadManForUser[] = {0xA66B0120,&WrapU_IU, "sceKernelReferEventFlagStatus"}, {0x8FFDF9A2,&WrapV_IIU, "sceKernelCancelSema"}, - {0xD6DA4BA1,&WrapI_CUIIU, "sceKernelCreateSema"}, + {0xD6DA4BA1,&WrapV_CUIIU, "sceKernelCreateSema"}, {0x28b6489c,&WrapV_I, "sceKernelDeleteSema"}, - {0x58b1f937,&WrapI_II, "sceKernelPollSema"}, - {0xBC6FEBC5,&WrapI_IU, "sceKernelReferSemaStatus"}, + {0x58b1f937,&WrapV_II, "sceKernelPollSema"}, + {0xBC6FEBC5,&WrapV_IU, "sceKernelReferSemaStatus"}, {0x3F53E640,&WrapV_II, "sceKernelSignalSema"}, {0x4E3A1105,&WrapV_IIU, "sceKernelWaitSema"}, {0x6d212bac,&WrapV_IIU, "sceKernelWaitSemaCB"}, diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index c09109a39d..ee015af652 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -112,7 +112,6 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) // We need to set the return value BEFORE rescheduling threads. RETURN(0); - // Cancel appears to always reschedule. __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL); __KernelReSchedule("semaphore cancelled"); } @@ -124,10 +123,14 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) } //SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); -SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) +// void because it changes threads. +void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { if (!name) - return SCE_KERNEL_ERROR_ERROR; + { + RETURN(SCE_KERNEL_ERROR_ERROR); + return; + } Semaphore *s = new Semaphore; SceUID id = kernelObjects.Create(s); @@ -143,7 +146,9 @@ SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, DEBUG_LOG(HLE,"%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr); - return id; + RETURN(id); + + __KernelReSchedule("semaphore created"); } //int sceKernelDeleteSema(SceUID semaid); @@ -156,13 +161,9 @@ void sceKernelDeleteSema(SceUID id) Semaphore *s = kernelObjects.Get(id, error); if (s) { - if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE)) - { - RETURN(kernelObjects.Destroy(id)); - __KernelReSchedule("semaphore deleted"); - } - else - RETURN(kernelObjects.Destroy(id)); + __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE); + RETURN(kernelObjects.Destroy(id)); + __KernelReSchedule("semaphore deleted"); } else { @@ -171,7 +172,9 @@ void sceKernelDeleteSema(SceUID id) } } -int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) +//int sceKernelDeleteSema(SceUID semaid, SceKernelSemaInfo *info); +// void because it changes threads. +void sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { u32 error; Semaphore *s = kernelObjects.Get(id, error); @@ -179,12 +182,13 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, infoPtr); Memory::WriteStruct(infoPtr, &s->ns); - return 0; + RETURN(0); + __KernelReSchedule("semaphore refer status"); } else { ERROR_LOG(HLE,"Error %08x", error); - return error; + RETURN(error); } } @@ -234,9 +238,7 @@ retry: } } - // I don't think we should reschedule here - //if (wokeThreads) - // __KernelReSchedule("semaphore signalled"); + __KernelReSchedule("semaphore signalled"); } else { @@ -254,7 +256,7 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba // We need to set the return value BEFORE processing callbacks / etc. RETURN(0); - if (s->ns.currentCount >= wantedCount) //TODO fix + if (s->ns.currentCount >= wantedCount) s->ns.currentCount -= wantedCount; else { @@ -265,6 +267,8 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba if (processCallbacks) __KernelCheckCallbacks(); } + + __KernelReSchedule("semaphore waited"); } else { @@ -292,30 +296,34 @@ void sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) } // Should be same as WaitSema but without the wait, instead returning SCE_KERNEL_ERROR_SEMA_ZERO -int sceKernelPollSema(SceUID id, int wantedCount) +void sceKernelPollSema(SceUID id, int wantedCount) { DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount); if (wantedCount <= 0) - return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + { + RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT); + return; + } u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { - if (s->ns.currentCount >= wantedCount) //TODO fix - s->ns.currentCount -= wantedCount; - else + if (s->ns.currentCount >= wantedCount) { - return SCE_KERNEL_ERROR_SEMA_ZERO; + s->ns.currentCount -= wantedCount; + RETURN(0); } + else + RETURN(SCE_KERNEL_ERROR_SEMA_ZERO); - return 0; + __KernelReSchedule("semaphore polled"); } else { ERROR_LOG(HLE, "sceKernelPollSema: Trying to poll invalid semaphore %i", id); - return error; + RETURN(error); } } diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index 86d51e1b9b..4027fda2d8 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -18,10 +18,10 @@ #pragma once void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr); -SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr); +void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr); void sceKernelDeleteSema(SceUID id); -int sceKernelPollSema(SceUID id, int wantedCount); -int sceKernelReferSemaStatus(SceUID id, u32 infoPtr); +void sceKernelPollSema(SceUID id, int wantedCount); +void sceKernelReferSemaStatus(SceUID id, u32 infoPtr); void sceKernelSignalSema(SceUID id, int signal); void sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr); void sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); diff --git a/test.py b/test.py index c3e0107ab0..f1642fc6f8 100644 --- a/test.py +++ b/test.py @@ -33,6 +33,12 @@ tests_good = [ "gpu/callbacks/ge_callbacks", "threads/mbx/mbx", "threads/semaphores/semaphores", + "threads/semaphores/cancel/cancel", + "threads/semaphores/create/create", + "threads/semaphores/delete/delete", + "threads/semaphores/poll/poll", + "threads/semaphores/refer/refer", + "threads/semaphores/signal/signal", "power/power", "rtc/rtc", "umd/callbacks/umd", @@ -45,6 +51,8 @@ tests_next = [ "threads/msgpipe/msgpipe", "threads/mutex/mutex", "threads/scheduling/scheduling", + "threads/semaphores/priority/priority", + "threads/semaphores/wait/wait", "threads/threads/threads", "threads/vpl/vpl", "threads/vtimers/vtimer",