mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 16:49:50 +00:00
Implement sceKernelCancelMutex().
This commit is contained in:
parent
18832f3ca7
commit
d547d2b391
@ -685,14 +685,14 @@ const HLEFunction ThreadManForUser[] =
|
||||
//{0x31327F19,0, "_sceKernelLockLwMutexCB"},
|
||||
//{0xBEED3A47,0, "_sceKernelUnlockLwMutex"},
|
||||
|
||||
{0xf8170fbe,&WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
|
||||
{0xB011B11F,&WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex", HLE_NOT_DISPATCH_SUSPENDED},
|
||||
{0x5bf4dd27,&WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB", HLE_NOT_DISPATCH_SUSPENDED},
|
||||
{0x6b30100f,&WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
|
||||
{0xb7d098c6,&WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
|
||||
{0x0DDCD2C9,&WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
|
||||
{0xA9C2CB9A,&WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
|
||||
{0x87D9223C,0, "sceKernelCancelMutex"},
|
||||
{0xf8170fbe,WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
|
||||
{0xB011B11F,WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex", HLE_NOT_DISPATCH_SUSPENDED},
|
||||
{0x5bf4dd27,WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB", HLE_NOT_DISPATCH_SUSPENDED},
|
||||
{0x6b30100f,WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
|
||||
{0xb7d098c6,WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
|
||||
{0x0DDCD2C9,WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
|
||||
{0xA9C2CB9A,WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
|
||||
{0x87D9223C,WrapI_IIU<sceKernelCancelMutex>, "sceKernelCancelMutex"},
|
||||
|
||||
{0xFCCFAD26,WrapI_I<sceKernelCancelWakeupThread>,"sceKernelCancelWakeupThread"},
|
||||
{0x1AF94D03,0,"sceKernelDonateWakeupThread"},
|
||||
|
@ -405,11 +405,11 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio
|
||||
|
||||
int sceKernelDeleteMutex(SceUID id)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id);
|
||||
u32 error;
|
||||
Mutex *mutex = kernelObjects.Get<Mutex>(id, error);
|
||||
if (mutex)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelDeleteMutex(%i)", id);
|
||||
bool wokeThreads = false;
|
||||
std::vector<SceUID>::iterator iter, end;
|
||||
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
@ -425,7 +425,10 @@ int sceKernelDeleteMutex(SceUID id)
|
||||
return kernelObjects.Destroy<Mutex>(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelDeleteMutex(%i): invalid mutex", id);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
bool __KernelLockMutexCheck(Mutex *mutex, int count, u32 &error)
|
||||
@ -567,6 +570,65 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr)
|
||||
CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread());
|
||||
}
|
||||
|
||||
int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr)
|
||||
{
|
||||
u32 error;
|
||||
Mutex *mutex = kernelObjects.Get<Mutex>(uid, error);
|
||||
if (mutex)
|
||||
{
|
||||
bool lockable = count <= 0 || __KernelLockMutexCheck(mutex, count, error);
|
||||
if (!lockable)
|
||||
{
|
||||
// May still be okay. As long as the count/etc. are valid.
|
||||
if (error != 0 && error != PSP_MUTEX_ERROR_LOCK_OVERFLOW && error != PSP_MUTEX_ERROR_ALREADY_LOCKED)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x): invalid count", uid, count, numWaitThreadsPtr);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x)", uid, count, numWaitThreadsPtr);
|
||||
|
||||
// Remove threads no longer waiting on this first (so the numWaitThreads value is correct.)
|
||||
for (auto iter = mutex->waitingThreads.begin(); iter != mutex->waitingThreads.end(); ++iter)
|
||||
{
|
||||
SceUID waitID = __KernelGetWaitID(*iter, WAITTYPE_MUTEX, error);
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (waitID != uid)
|
||||
mutex->waitingThreads.erase(iter--);
|
||||
}
|
||||
|
||||
if (Memory::IsValidAddress(numWaitThreadsPtr))
|
||||
Memory::Write_U32((u32)mutex->waitingThreads.size(), numWaitThreadsPtr);
|
||||
|
||||
bool wokeThreads = false;
|
||||
for (auto iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
|
||||
wokeThreads |= __KernelUnlockMutexForThread(mutex, *iter, error, SCE_KERNEL_ERROR_WAIT_CANCEL);
|
||||
|
||||
if (mutex->nm.lockThread != -1)
|
||||
__KernelMutexEraseLock(mutex);
|
||||
mutex->waitingThreads.clear();
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
mutex->nm.lockLevel = 0;
|
||||
mutex->nm.lockThread = -1;
|
||||
}
|
||||
else
|
||||
__KernelMutexAcquireLock(mutex, count);
|
||||
|
||||
if (wokeThreads)
|
||||
hleReSchedule("mutex canceled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelCancelMutex(%i, %d, %08x)", uid, count, numWaitThreadsPtr);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// int sceKernelLockMutex(SceUID id, int count, int *timeout)
|
||||
int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr);
|
||||
int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr);
|
||||
int sceKernelDeleteMutex(SceUID id);
|
||||
int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr);
|
||||
|
Loading…
Reference in New Issue
Block a user