mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-26 01:40:24 +00:00
Implement sceKernelReferLwMutexStatus() and ByID().
This commit is contained in:
parent
ad3152cb94
commit
37dffb6210
@ -540,35 +540,37 @@ u32 sceKernelReferGlobalProfiler(u32 statusPtr) {
|
||||
|
||||
const HLEFunction ThreadManForUser[] =
|
||||
{
|
||||
{0x55C20A00,&WrapI_CUUU<sceKernelCreateEventFlag>, "sceKernelCreateEventFlag"},
|
||||
{0x812346E4,&WrapU_IU<sceKernelClearEventFlag>, "sceKernelClearEventFlag"},
|
||||
{0xEF9E4C70,&WrapU_I<sceKernelDeleteEventFlag>, "sceKernelDeleteEventFlag"},
|
||||
{0x1fb15a32,&WrapU_IU<sceKernelSetEventFlag>, "sceKernelSetEventFlag"},
|
||||
{0x402FCF22,&WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag"},
|
||||
{0x328C546A,&WrapI_IUUUU<sceKernelWaitEventFlagCB>, "sceKernelWaitEventFlagCB"},
|
||||
{0x30FD48F0,&WrapI_IUUUU<sceKernelPollEventFlag>, "sceKernelPollEventFlag"},
|
||||
{0xCD203292,&WrapU_IUU<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag"},
|
||||
{0xA66B0120,&WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus"},
|
||||
{0x55C20A00,&WrapI_CUUU<sceKernelCreateEventFlag>, "sceKernelCreateEventFlag"},
|
||||
{0x812346E4,&WrapU_IU<sceKernelClearEventFlag>, "sceKernelClearEventFlag"},
|
||||
{0xEF9E4C70,&WrapU_I<sceKernelDeleteEventFlag>, "sceKernelDeleteEventFlag"},
|
||||
{0x1fb15a32,&WrapU_IU<sceKernelSetEventFlag>, "sceKernelSetEventFlag"},
|
||||
{0x402FCF22,&WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag"},
|
||||
{0x328C546A,&WrapI_IUUUU<sceKernelWaitEventFlagCB>, "sceKernelWaitEventFlagCB"},
|
||||
{0x30FD48F0,&WrapI_IUUUU<sceKernelPollEventFlag>, "sceKernelPollEventFlag"},
|
||||
{0xCD203292,&WrapU_IUU<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag"},
|
||||
{0xA66B0120,&WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus"},
|
||||
|
||||
{0x8FFDF9A2,&WrapI_IIU<sceKernelCancelSema>, "sceKernelCancelSema"},
|
||||
{0xD6DA4BA1,&WrapI_CUIIU<sceKernelCreateSema>, "sceKernelCreateSema"},
|
||||
{0x28b6489c,&WrapI_I<sceKernelDeleteSema>, "sceKernelDeleteSema"},
|
||||
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
|
||||
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
|
||||
{0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"},
|
||||
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema"},
|
||||
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"},
|
||||
{0x8FFDF9A2,&WrapI_IIU<sceKernelCancelSema>, "sceKernelCancelSema"},
|
||||
{0xD6DA4BA1,&WrapI_CUIIU<sceKernelCreateSema>, "sceKernelCreateSema"},
|
||||
{0x28b6489c,&WrapI_I<sceKernelDeleteSema>, "sceKernelDeleteSema"},
|
||||
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
|
||||
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
|
||||
{0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"},
|
||||
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema"},
|
||||
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"},
|
||||
|
||||
{0x60107536,&WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex"},
|
||||
{0x19CFF145,&WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex"},
|
||||
{0xf8170fbe,&WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
|
||||
{0xB011B11F,&WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex"},
|
||||
{0x5bf4dd27,&WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB"},
|
||||
{0x6b30100f,&WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
|
||||
{0xb7d098c6,&WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
|
||||
{0x0DDCD2C9,&WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
|
||||
{0xA9C2CB9A,&WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
|
||||
// NOTE: LockLwMutex and UnlockLwMutex are in Kernel_Library, see sceKernelInterrupt.cpp.
|
||||
{0x60107536,&WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex"},
|
||||
{0x19CFF145,&WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex"},
|
||||
{0x4C145944,&WrapI_IU<sceKernelReferLwMutexStatusByID>, "sceKernelReferLwMutexStatusByID"},
|
||||
// NOTE: LockLwMutex, UnlockLwMutex, and ReferLwMutexStatus are in Kernel_Library, see sceKernelInterrupt.cpp.
|
||||
|
||||
{0xf8170fbe,&WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex"},
|
||||
{0xB011B11F,&WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex"},
|
||||
{0x5bf4dd27,&WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB"},
|
||||
{0x6b30100f,&WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex"},
|
||||
{0xb7d098c6,&WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex"},
|
||||
{0x0DDCD2C9,&WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex"},
|
||||
{0xA9C2CB9A,&WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus"},
|
||||
|
||||
{0xFCCFAD26,sceKernelCancelWakeupThread,"sceKernelCancelWakeupThread"},
|
||||
{0xea748e31,sceKernelChangeCurrentThreadAttr,"sceKernelChangeCurrentThreadAttr"},
|
||||
|
@ -553,6 +553,7 @@ const HLEFunction Kernel_Library[] =
|
||||
{0xbea46419,WrapI_UIU<sceKernelLockLwMutex>, "sceKernelLockLwMutex"},
|
||||
{0x1FC64E09,WrapI_UIU<sceKernelLockLwMutexCB>, "sceKernelLockLwMutexCB"},
|
||||
{0x15b6446b,WrapI_UI<sceKernelUnlockLwMutex>, "sceKernelUnlockLwMutex"},
|
||||
{0xc1734599,WrapI_UU<sceKernelReferLwMutexStatus>, "sceKernelReferLwMutexStatus"},
|
||||
{0x293b45b8,sceKernelGetThreadId, "sceKernelGetThreadId"},
|
||||
{0x1839852A,WrapU_UUU<sceKernelMemcpy>,"sce_paf_private_memcpy"},
|
||||
};
|
||||
|
@ -46,7 +46,6 @@
|
||||
#define PSP_LWMUTEX_ERROR_UNLOCK_UNDERFLOW 0x800201CE
|
||||
#define PSP_LWMUTEX_ERROR_ALREADY_LOCKED 0x800201CF
|
||||
|
||||
// Guesswork - not exposed anyway
|
||||
struct NativeMutex
|
||||
{
|
||||
SceSize size;
|
||||
@ -55,6 +54,7 @@ struct NativeMutex
|
||||
int initialCount;
|
||||
int lockLevel;
|
||||
SceUID lockThread;
|
||||
// Not kept up to date.
|
||||
int numWaitThreads;
|
||||
};
|
||||
|
||||
@ -77,13 +77,21 @@ struct Mutex : public KernelObject
|
||||
std::vector<SceUID> waitingThreads;
|
||||
};
|
||||
|
||||
// Guesswork - not exposed anyway
|
||||
|
||||
struct NativeLwMutex
|
||||
{
|
||||
SceSize size;
|
||||
char name[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||
SceUInt attr;
|
||||
SceUInt workareaPtr;
|
||||
SceUID uid;
|
||||
u32 workareaPtr;
|
||||
int initialCount;
|
||||
// Not kept up to date.
|
||||
int currentCount;
|
||||
// Not kept up to date.
|
||||
SceUID lockThread;
|
||||
// Not kept up to date.
|
||||
int numWaitThreads;
|
||||
};
|
||||
|
||||
struct NativeLwMutexWorkarea
|
||||
@ -543,6 +551,32 @@ int sceKernelUnlockMutex(SceUID id, int count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceKernelReferMutexStatus(SceUID id, u32 infoAddr)
|
||||
{
|
||||
u32 error;
|
||||
Mutex *m = kernelObjects.Get<Mutex>(id, error);
|
||||
if (!m)
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelReferMutexStatus(%i, %08x): invalid mutex id", id, infoAddr);
|
||||
return error;
|
||||
}
|
||||
|
||||
DEBUG_LOG(HLE, "sceKernelReferMutexStatus(%08x, %08x)", id, infoAddr);
|
||||
|
||||
// Should we crash the thread somehow?
|
||||
if (!Memory::IsValidAddress(infoAddr))
|
||||
return -1;
|
||||
|
||||
// Don't write if the size is 0. Anything else is A-OK, though, apparently.
|
||||
if (Memory::Read_U32(infoAddr) != 0)
|
||||
{
|
||||
// Refresh and write
|
||||
m->nm.numWaitThreads = m->waitingThreads.size();
|
||||
Memory::WriteStruct(infoAddr, &m->nm);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr)
|
||||
{
|
||||
if (!name)
|
||||
@ -563,11 +597,13 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init
|
||||
|
||||
LwMutex *mutex = new LwMutex();
|
||||
SceUID id = kernelObjects.Create(mutex);
|
||||
mutex->nm.size = sizeof(mutex);
|
||||
mutex->nm.size = sizeof(mutex->nm);
|
||||
strncpy(mutex->nm.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
|
||||
mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
|
||||
mutex->nm.attr = attr;
|
||||
mutex->nm.uid = id;
|
||||
mutex->nm.workareaPtr = workareaPtr;
|
||||
mutex->nm.initialCount = initialCount;
|
||||
NativeLwMutexWorkarea workarea;
|
||||
workarea.init();
|
||||
workarea.lockLevel = initialCount;
|
||||
@ -590,30 +626,6 @@ 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<Mutex>(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;
|
||||
|
||||
// Don't write if the size is 0. Anything else is A-OK, though, apparently.
|
||||
if (Memory::Read_U32(infoAddr) != 0)
|
||||
{
|
||||
// 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);
|
||||
@ -928,3 +940,64 @@ int sceKernelUnlockLwMutex(u32 workareaPtr, int count)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __KernelReferLwMutexStatus(SceUID uid, u32 infoPtr)
|
||||
{
|
||||
u32 error;
|
||||
LwMutex *m = kernelObjects.Get<LwMutex>(uid, error);
|
||||
if (!m)
|
||||
return error;
|
||||
|
||||
// Should we crash the thread somehow?
|
||||
if (!Memory::IsValidAddress(infoPtr))
|
||||
return -1;
|
||||
|
||||
if (Memory::Read_U32(infoPtr) != 0)
|
||||
{
|
||||
NativeLwMutexWorkarea workarea;
|
||||
Memory::ReadStruct(m->nm.workareaPtr, &workarea);
|
||||
|
||||
// Refresh and write
|
||||
m->nm.currentCount = workarea.lockLevel;
|
||||
m->nm.lockThread = workarea.lockThread == 0 ? -1 : workarea.lockThread;
|
||||
m->nm.numWaitThreads = m->waitingThreads.size();
|
||||
Memory::WriteStruct(infoPtr, &m->nm);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceKernelReferLwMutexStatusByID(SceUID uid, u32 infoPtr)
|
||||
{
|
||||
int error = __KernelReferLwMutexStatus(uid, infoPtr);
|
||||
if (error >= 0)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelReferLwMutexStatusByID(%08x, %08x)", uid, infoPtr);
|
||||
return error;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "%08x=sceKernelReferLwMutexStatusByID(%08x, %08x)", error, uid, infoPtr);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
int sceKernelReferLwMutexStatus(u32 workareaPtr, u32 infoPtr)
|
||||
{
|
||||
if (!Memory::IsValidAddress(workareaPtr))
|
||||
return -1;
|
||||
|
||||
NativeLwMutexWorkarea workarea;
|
||||
Memory::ReadStruct(workareaPtr, &workarea);
|
||||
|
||||
int error = __KernelReferLwMutexStatus(workarea.uid, infoPtr);
|
||||
if (error >= 0)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceKernelReferLwMutexStatus(%08x, %08x)", workareaPtr, infoPtr);
|
||||
return error;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "%08x=sceKernelReferLwMutexStatus(%08x, %08x)", error, workareaPtr, infoPtr);
|
||||
return error;
|
||||
}
|
||||
}
|
@ -32,6 +32,8 @@ int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count);
|
||||
int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr);
|
||||
int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr);
|
||||
int sceKernelUnlockLwMutex(u32 workareaPtr, int count);
|
||||
int sceKernelReferLwMutexStatusByID(SceUID uid, u32 infoPtr);
|
||||
int sceKernelReferLwMutexStatus(u32 workareaPtr, u32 infoPtr);
|
||||
|
||||
void __KernelMutexTimeout(u64 userdata, int cyclesLate);
|
||||
void __KernelLwMutexTimeout(u64 userdata, int cyclesLate);
|
||||
|
Loading…
Reference in New Issue
Block a user