From 4bfa24eca8e7a4b9deaf792e13fb19c99291247e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Nov 2012 19:34:39 -0800 Subject: [PATCH] Fix sceKernelCreateMutex() to match tests. Still have an issue where reusing threads doesn't work. --- Core/HLE/FunctionWrappers.h | 9 ++++---- Core/HLE/sceKernel.cpp | 2 +- Core/HLE/sceKernelMutex.cpp | 44 ++++++++++++++++++++++++++++--------- Core/HLE/sceKernelMutex.h | 3 +-- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index cf131bfb0..224f39a52 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -118,11 +118,6 @@ template void WrapI_CUUU() { RETURN(retval); } -template void WrapI_CUIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); - 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_CUIU() { + func(Memory::GetCharPointer(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)); } diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 3132c16a8..eee7c7510 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -343,7 +343,7 @@ const HLEFunction ThreadManForUser[] = {0xB011B11F,&WrapV_IIU,"sceKernelLockMutex"}, {0x5bf4dd27,&WrapV_IIU,"sceKernelLockMutexCB"}, {0x6b30100f,&WrapV_II,"sceKernelUnlockMutex"}, - {0xb7d098c6,&WrapI_CUIU,"sceKernelCreateMutex"}, + {0xb7d098c6,&WrapV_CUIU,"sceKernelCreateMutex"}, {0x0DDCD2C9, 0, "sceKernelTryLockMutex"}, // NOTE: LockLwMutex and UnlockLwMutex are in Kernel_Library, see sceKernelInterrupt.cpp. diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 2cad2461c..39db77bfd 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -47,7 +47,7 @@ struct Mutex : public KernelObject { const char *GetName() {return nm.name;} const char *GetTypeName() {return "Mutex";} - static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_SEMID; } // Not sure? + static u32 GetMissingErrorCode() { return PSP_MUTEX_ERROR_NO_SUCH_MUTEX; } // Not sure? int GetIDType() const { return SCE_KERNEL_TMID_Mutex; } NativeMutex nm; std::vector waitingThreads; @@ -63,21 +63,37 @@ struct LWMutex : public KernelObject std::vector waitingThreads; }; -SceUID sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) +void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { + u32 error = 0; + if (!error && !name) + error = SCE_KERNEL_ERROR_ERROR; + if (!error && initialCount < 0) + error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + if (!error && (attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1) + error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + + if (error) + { + RETURN(error); + return; + } + DEBUG_LOG(HLE,"sceKernelCreateMutex(%s, %08x, %d, %08x)", name, attr, initialCount, optionsPtr); Mutex *mutex = new Mutex(); SceUID id = kernelObjects.Create(mutex); mutex->nm.size = sizeof(mutex); + strncpy(mutex->nm.name, name, 31); + mutex->nm.name[31] = 0; mutex->nm.attr = attr; mutex->nm.lockLevel = initialCount; - // TODO: Does initial_count > 0 mean lock automatically by the current thread? Would make sense. - mutex->nm.lockThread = -1; + mutex->nm.lockThread = __KernelGetCurThread(); - strncpy(mutex->nm.name, name, 32); - return id; + RETURN(id); + + __KernelReSchedule("mutex created"); } void sceKernelDeleteMutex(SceUID id) @@ -87,13 +103,21 @@ void sceKernelDeleteMutex(SceUID id) Mutex *mutex = kernelObjects.Get(id, error); if (mutex) { - RETURN(0); + std::vector::iterator iter, end; + for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) + { + SceUID threadID = *iter; - kernelObjects.Destroy(id); - // TODO: Almost certainly need to reschedule (sometimes?) + // TODO: Set returnValue? + __KernelResumeThreadFromWait(threadID); + } + mutex->waitingThreads.empty(); + + RETURN(kernelObjects.Destroy(id)); + __KernelReSchedule("mutex deleted"); } else - RETURN(PSP_MUTEX_ERROR_NO_SUCH_MUTEX); + RETURN(error); } // int sceKernelLockMutex(SceUID id, int count, int *timeout) diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index 21713dba8..388d7d767 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -17,8 +17,7 @@ #pragma once -// TODO -SceUID sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr); +void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr); void sceKernelDeleteMutex(SceUID id); void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr); void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr);