From 8d845cc5885000063597ca0f3be7a767489b570e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jan 2013 23:11:48 +0100 Subject: [PATCH] quick implementation of sceKernelReferMutexStatus --- Core/HLE/sceKernel.cpp | 1 + Core/HLE/sceKernelMutex.cpp | 46 +++++++++++++++++++++++++++---------- Core/HLE/sceKernelMutex.h | 1 + 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index dfcbffb5a6..131c848fb5 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -532,6 +532,7 @@ const HLEFunction ThreadManForUser[] = {0x6b30100f,&WrapI_II, "sceKernelUnlockMutex"}, {0xb7d098c6,&WrapI_CUIU, "sceKernelCreateMutex"}, {0x0DDCD2C9,&WrapI_II, "sceKernelTryLockMutex"}, + {0xA9C2CB9A,&WrapI_IU, "sceKernelReferMutexStatus"}, // NOTE: LockLwMutex and UnlockLwMutex are in Kernel_Library, see sceKernelInterrupt.cpp. {0xFCCFAD26,sceKernelCancelWakeupThread,"sceKernelCancelWakeupThread"}, diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 2bf7c25439..9042fcb58b 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -51,9 +51,9 @@ struct NativeMutex SceSize size; char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; SceUInt attr; - + int initialCount; int lockLevel; - int lockThread; // The thread holding the lock + int numWaitThreads; }; struct Mutex : public KernelObject @@ -68,11 +68,13 @@ struct Mutex : public KernelObject p.Do(nm); SceUID dv = 0; p.Do(waitingThreads, dv); + p.Do(lockThread); p.DoMarker("Mutex"); } NativeMutex nm; std::vector waitingThreads; + int lockThread; // The thread holding the lock }; // Guesswork - not exposed anyway @@ -175,7 +177,7 @@ void __KernelMutexAcquireLock(Mutex *mutex, int count, SceUID thread) mutexHeldLocks.insert(std::make_pair(thread, mutex->GetUID())); mutex->nm.lockLevel = count; - mutex->nm.lockThread = thread; + mutex->lockThread = thread; } void __KernelMutexAcquireLock(Mutex *mutex, int count) @@ -185,10 +187,10 @@ void __KernelMutexAcquireLock(Mutex *mutex, int count) void __KernelMutexEraseLock(Mutex *mutex) { - if (mutex->nm.lockThread != -1) + if (mutex->lockThread != -1) { SceUID id = mutex->GetUID(); - std::pair locked = mutexHeldLocks.equal_range(mutex->nm.lockThread); + std::pair locked = mutexHeldLocks.equal_range(mutex->lockThread); for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { if ((*iter).second == id) @@ -198,7 +200,7 @@ void __KernelMutexEraseLock(Mutex *mutex) } } } - mutex->nm.lockThread = -1; + mutex->lockThread = -1; } std::vector::iterator __KernelMutexFindPriority(std::vector &waiting) @@ -246,10 +248,11 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio strncpy(mutex->nm.name, name, KERNELOBJECT_MAX_NAME_LENGTH); mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; mutex->nm.attr = attr; + mutex->nm.initialCount = initialCount; if (initialCount == 0) { mutex->nm.lockLevel = 0; - mutex->nm.lockThread = -1; + mutex->lockThread = -1; } else __KernelMutexAcquireLock(mutex, initialCount); @@ -303,7 +306,7 @@ int sceKernelDeleteMutex(SceUID id) for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) wokeThreads |= __KernelUnlockMutexForThread(mutex, *iter, error, SCE_KERNEL_ERROR_WAIT_DELETE); - if (mutex->nm.lockThread != -1) + if (mutex->lockThread != -1) __KernelMutexEraseLock(mutex); mutex->waitingThreads.clear(); @@ -339,7 +342,7 @@ bool __KernelLockMutex(Mutex *mutex, int count, u32 &error) return true; } - if (mutex->nm.lockThread == __KernelGetCurThread()) + if (mutex->lockThread == __KernelGetCurThread()) { // Recursive mutex, let's just increase the lock count and keep going if (mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) @@ -375,7 +378,7 @@ bool __KernelUnlockMutex(Mutex *mutex, u32 &error) } if (!wokeThreads) - mutex->nm.lockThread = -1; + mutex->lockThread = -1; return wokeThreads; } @@ -524,7 +527,7 @@ int sceKernelUnlockMutex(SceUID id, int count) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; if ((mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - if (mutex->nm.lockLevel == 0 || mutex->nm.lockThread != __KernelGetCurThread()) + if (mutex->nm.lockLevel == 0 || mutex->lockThread != __KernelGetCurThread()) return PSP_MUTEX_ERROR_NOT_LOCKED; if (mutex->nm.lockLevel < count) return PSP_MUTEX_ERROR_UNLOCK_UNDERFLOW; @@ -565,7 +568,6 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; mutex->nm.attr = attr; mutex->nm.workareaPtr = workareaPtr; - NativeLwMutexWorkarea workarea; workarea.init(); workarea.lockLevel = initialCount; @@ -588,6 +590,26 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init return 0; } +int sceKernelReferMutexStatus(SceUID id, u32 infoAddr) +{ + u32 error; + Mutex *m = kernelObjects.Get(id, error); + if (!m) + { + ERROR_LOG(HLE, "sceKernelReferMutexStatus(%i, %08x): invalid mbx id", id, infoAddr); + return error; + } + + // Should we crash the thread somehow? + if (!Memory::IsValidAddress(infoAddr)) + return -1; + + // Refresh and write + m->nm.numWaitThreads = m->waitingThreads.size(); + Memory::WriteStruct(infoAddr, &m->nm); + return 0; +} + bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &workarea, SceUID threadID, u32 &error, int result) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index 18eeb4fafb..259f9f886c 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -23,6 +23,7 @@ int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr); int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr); int sceKernelTryLockMutex(SceUID id, int count); int sceKernelUnlockMutex(SceUID id, int count); +int sceKernelReferMutexStatus(SceUID id, u32 infoAddr); int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr); int sceKernelDeleteLwMutex(u32 workareaPtr);