Implement sceKernelReferLwMutexStatus() and ByID().

This commit is contained in:
Unknown W. Brackets 2013-02-24 22:50:48 -08:00
parent ad3152cb94
commit 37dffb6210
4 changed files with 133 additions and 55 deletions

View File

@ -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"},

View File

@ -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"},
};

View File

@ -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;
}
}

View File

@ -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);