diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 54d541b59b..27f6bb8cf0 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -57,7 +57,6 @@ struct Mutex : public KernelObject int GetIDType() const { return SCE_KERNEL_TMID_Mutex; } NativeMutex nm; std::vector waitingThreads; - int waitTimer; }; // Guesswork - not exposed anyway @@ -99,11 +98,25 @@ struct LwMutex : public KernelObject int GetIDType() const { return SCE_KERNEL_TMID_LwMutex; } NativeLwMutex nm; std::vector waitingThreads; - int waitTimer; }; +bool mutexInitComplete = false; +int mutexWaitTimer = 0; +int lwMutexWaitTimer = 0; + +void __KernelMutexInit() +{ + mutexWaitTimer = CoreTiming::RegisterEvent("MutexTimeout", &__KernelMutexTimeout); + // TODO: Write / enable. + //lwMutexWaitTimer = CoreTiming::RegisterEvent("LwMutexTimeout", &__KernelLwMutexTimeout); + mutexInitComplete = true; +} + void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { + if (!mutexInitComplete) + __KernelMutexInit(); + u32 error = 0; if (!name) error = SCE_KERNEL_ERROR_ERROR; @@ -132,7 +145,6 @@ void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 opti mutex->nm.lockThread = -1; else mutex->nm.lockThread = __KernelGetCurThread(); - mutex->waitTimer = 0; if (optionsPtr != 0) WARN_LOG(HLE,"sceKernelCreateMutex(%s) unsupported options parameter.", name); @@ -155,10 +167,10 @@ void sceKernelDeleteMutex(SceUID id) SceUID threadID = *iter; u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && mutex->waitTimer != 0) + if (timeoutPtr != 0 && mutexWaitTimer != 0) { // Remove any event for this thread. - int cyclesLeft = CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID); + int cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr); } @@ -166,8 +178,6 @@ void sceKernelDeleteMutex(SceUID id) } mutex->waitingThreads.empty(); - // TODO: Any way to erase the CoreTiming event type? We leak. - RETURN(kernelObjects.Destroy(id)); __KernelReSchedule("mutex deleted"); } @@ -231,15 +241,12 @@ void __KernelMutexTimeout(u64 userdata, int cyclesLate) void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) { - if (timeoutPtr == 0) + if (timeoutPtr == 0 || mutexWaitTimer == 0) return; - if (mutex->waitTimer == 0) - mutex->waitTimer = CoreTiming::RegisterEvent("MutexTimeout", &__KernelMutexTimeout); - // This should call __KernelMutexTimeout() later, unless we cancel it. int micro = (int) Memory::Read_U32(timeoutPtr); - CoreTiming::ScheduleEvent(usToCycles(micro), mutex->waitTimer, __KernelGetCurThread()); + CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread()); } // int sceKernelLockMutex(SceUID id, int count, int *timeout) @@ -356,10 +363,10 @@ void sceKernelUnlockMutex(SceUID id, int count) mutex->nm.lockThread = threadID; mutex->nm.lockLevel = wVal; - if (timeoutPtr != 0 && mutex->waitTimer != 0) + if (timeoutPtr != 0 && mutexWaitTimer != 0) { // Remove any event for this thread. - int cyclesLeft = CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID); + int cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr); } @@ -375,6 +382,9 @@ void sceKernelUnlockMutex(SceUID id, int count) void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr) { + if (!mutexInitComplete) + __KernelMutexInit(); + DEBUG_LOG(HLE,"sceKernelCreateLwMutex(%08x, %s, %08x, %d, %08x)", workareaPtr, name, attr, initialCount, optionsPtr); u32 error = 0; @@ -398,7 +408,6 @@ void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int ini mutex->nm.name[31] = 0; mutex->nm.attr = attr; mutex->nm.workareaPtr = workareaPtr; - mutex->waitTimer = 0; NativeLwMutexWorkarea workarea; workarea.init(); @@ -443,10 +452,10 @@ void sceKernelDeleteLwMutex(u32 workareaPtr) SceUID threadID = *iter; u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && mutex->waitTimer != 0) + if (timeoutPtr != 0 && lwMutexWaitTimer != 0) { // Remove any event for this thread. - int cyclesLeft = CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID); + int cyclesLeft = CoreTiming::UnscheduleEvent(lwMutexWaitTimer, threadID); Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr); } @@ -454,8 +463,6 @@ void sceKernelDeleteLwMutex(u32 workareaPtr) } mutex->waitingThreads.empty(); - // TODO: Any way to erase the CoreTiming event type? We leak. - RETURN(kernelObjects.Destroy(workarea.uid)); workarea.clear(); Memory::WriteStruct(workareaPtr, &workarea); diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index 82dd7cfbc4..5f9e170fbd 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -29,4 +29,7 @@ void sceKernelDeleteLwMutex(u32 workareaPtr); void sceKernelTryLockLwMutex(); void sceKernelLockLwMutex(); void sceKernelLockLwMutexCB(); -void sceKernelUnlockLwMutex(); \ No newline at end of file +void sceKernelUnlockLwMutex(); + +void __KernelMutexTimeout(u64 userdata, int cyclesLate); +void __KernelLwMutexTimeout(u64 userdata, int cyclesLate); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 38dc56860e..bf48bfa423 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -59,9 +59,17 @@ struct Semaphore : public KernelObject NativeSemaphore ns; std::vector waitingThreads; - int waitTimer; }; +bool semaInitComplete = false; +int semaWaitTimer = 0; + +void __KernelSemaInit() +{ + semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout); + semaInitComplete = true; +} + // Resume all waiting threads (for delete / cancel.) // Returns true if it woke any threads. bool __KernelClearSemaThreads(Semaphore *s, int reason) @@ -76,21 +84,18 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason) u32 error; u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && s->waitTimer != 0) + if (timeoutPtr != 0 && semaWaitTimer != 0) { // Remove any event for this thread. - int cyclesLeft = CoreTiming::UnscheduleEvent(s->waitTimer, threadID); + int cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr); } __KernelResumeThreadFromWait(threadID, reason); wokeThreads = true; - // TODO: set timeoutPtr. } s->waitingThreads.empty(); - // TODO: Any way to erase the CoreTiming event type? We leak. - return wokeThreads; } @@ -139,6 +144,9 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) // void because it changes threads. void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { + if (!semaInitComplete) + __KernelSemaInit(); + if (!name) { RETURN(SCE_KERNEL_ERROR_ERROR); @@ -156,7 +164,6 @@ void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u3 s->ns.currentCount = s->ns.initCount; s->ns.maxCount = maxVal; s->ns.numWaitThreads = 0; - s->waitTimer = 0; DEBUG_LOG(HLE,"%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr); @@ -247,10 +254,10 @@ retry: s->ns.currentCount -= wVal; s->ns.numWaitThreads--; - if (timeoutPtr != 0 && s->waitTimer != 0) + if (timeoutPtr != 0 && semaWaitTimer != 0) { // Remove any event for this thread. - int cyclesLeft = CoreTiming::UnscheduleEvent(s->waitTimer, threadID); + int cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr); } @@ -297,15 +304,12 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate) void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) { - if (timeoutPtr == 0) + if (timeoutPtr == 0 || semaWaitTimer == 0) return; - if (s->waitTimer == 0) - s->waitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout); - // This should call __KernelMutexTimeout() later, unless we cancel it. int micro = (int) Memory::Read_U32(timeoutPtr); - CoreTiming::ScheduleEvent(usToCycles(micro), s->waitTimer, __KernelGetCurThread()); + CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread()); } void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index 4027fda2d8..e6628fec9d 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -25,3 +25,5 @@ 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); + +void __KernelSemaTimeout(u64 userdata, int cycleslate);