mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Merge pull request #6675 from unknownbrackets/threadman
Correct sceKernelThreadmanIdList behavior
This commit is contained in:
commit
72d5a55791
3 files changed
+106
-27
No files matched your search
@@ -620,6 +620,7 @@ KernelObject *KernelObjectPool::CreateByIDType(int type)
|
||||
case SCE_KERNEL_TMID_VTimer:
|
||||
return __KernelVTimerObject();
|
||||
case SCE_KERNEL_TMID_Tlspl:
|
||||
case SCE_KERNEL_TMID_Tlspl_v0:
|
||||
return __KernelTlsplObject();
|
||||
case PPSSPP_KERNEL_TMID_File:
|
||||
return __KernelFileNodeObject();
|
||||
|
||||
+21
-6
@@ -327,12 +327,13 @@ enum TMIDPurpose
|
||||
SCE_KERNEL_TMID_VTimer = 11,
|
||||
SCE_KERNEL_TMID_Mutex = 12,
|
||||
SCE_KERNEL_TMID_LwMutex = 13,
|
||||
SCE_KERNEL_TMID_Tlspl = 14,
|
||||
SCE_KERNEL_TMID_SleepThread = 64,
|
||||
SCE_KERNEL_TMID_DelayThread = 65,
|
||||
SCE_KERNEL_TMID_SuspendThread = 66,
|
||||
SCE_KERNEL_TMID_DormantThread = 67,
|
||||
// No idea what the correct value is here or how to find out.
|
||||
SCE_KERNEL_TMID_Tlspl = 0x1001,
|
||||
// This is kept for old savestates. Not the real value.
|
||||
SCE_KERNEL_TMID_Tlspl_v0 = 0x1001,
|
||||
|
||||
// Not official, but need ids for save states.
|
||||
PPSSPP_KERNEL_TMID_Module = 0x100001,
|
||||
@@ -488,11 +489,9 @@ public:
|
||||
}
|
||||
|
||||
template <class T, typename ArgT>
|
||||
void Iterate(bool func(T *, ArgT), ArgT arg)
|
||||
{
|
||||
void Iterate(bool func(T *, ArgT), ArgT arg) {
|
||||
int type = T::GetStaticIDType();
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++) {
|
||||
if (!occupied[i])
|
||||
continue;
|
||||
T *t = static_cast<T *>(pool[i]);
|
||||
@@ -503,6 +502,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int ListIDType(int type, SceUID *uids, int count) const {
|
||||
int total = 0;
|
||||
for (int i = 0; i < maxCount; i++) {
|
||||
if (!occupied[i]) {
|
||||
continue;
|
||||
}
|
||||
if (pool[i]->GetIDType() == type) {
|
||||
if (total < count) {
|
||||
*uids++ = pool[i]->GetUID();
|
||||
}
|
||||
++total;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
bool GetIDType(SceUID handle, int *type) const
|
||||
{
|
||||
if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset])
|
||||
|
||||
@@ -507,9 +507,9 @@ public:
|
||||
void setReturnValue(u32 retval);
|
||||
void setReturnValue(u64 retval);
|
||||
void resumeFromWait();
|
||||
bool isWaitingFor(WaitType type, int id);
|
||||
int getWaitID(WaitType type);
|
||||
ThreadWaitInfo getWaitInfo();
|
||||
bool isWaitingFor(WaitType type, int id) const;
|
||||
int getWaitID(WaitType type) const;
|
||||
ThreadWaitInfo getWaitInfo() const;
|
||||
|
||||
// Utils
|
||||
inline bool isRunning() const { return (nt.status & THREADSTATUS_RUNNING) != 0; }
|
||||
@@ -1584,32 +1584,95 @@ int sceKernelGetThreadExitStatus(SceUID threadID)
|
||||
u32 sceKernelGetThreadmanIdType(u32 uid) {
|
||||
int type;
|
||||
if (kernelObjects.GetIDType(uid, &type)) {
|
||||
DEBUG_LOG(SCEKERNEL, "%i=sceKernelGetThreadmanIdType(%i)", type, uid);
|
||||
return type;
|
||||
if (type < 0x1000) {
|
||||
DEBUG_LOG(SCEKERNEL, "%i=sceKernelGetThreadmanIdType(%i)", type, uid);
|
||||
return type;
|
||||
} else {
|
||||
// This means a partition memory block or module, etc.
|
||||
ERROR_LOG(SCEKERNEL, "sceKernelGetThreadmanIdType(%i): invalid object type %i", uid, type);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(SCEKERNEL, "sceKernelGetThreadmanIdType(%i) - FAILED", uid);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr)
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)",
|
||||
type, readBufPtr, readBufSize, idCountPtr);
|
||||
if (!Memory::IsValidAddress(readBufPtr))
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
bool __ThreadmanIdListIsSleeping(const Thread *t) {
|
||||
return t->isWaitingFor(WAITTYPE_SLEEP, 0);
|
||||
}
|
||||
|
||||
if (type != SCE_KERNEL_TMID_Thread) {
|
||||
ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList only implemented for threads");
|
||||
bool __ThreadmanIdListIsDelayed(const Thread *t) {
|
||||
return t->isWaitingFor(WAITTYPE_DELAY, t->GetUID());
|
||||
}
|
||||
|
||||
bool __ThreadmanIdListIsSuspended(const Thread *t) {
|
||||
return t->isSuspended();
|
||||
}
|
||||
|
||||
bool __ThreadmanIdListIsDormant(const Thread *t) {
|
||||
return t->isStopped();
|
||||
}
|
||||
|
||||
u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr) {
|
||||
if (readBufSize >= 0x8000000) {
|
||||
// Not exact, it's probably if the sum ends up negative or something.
|
||||
ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid size", type, readBufPtr, readBufSize, idCountPtr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
|
||||
}
|
||||
if (!Memory::IsValidAddress(readBufPtr) && readBufSize > 0) {
|
||||
// Crashes on a PSP.
|
||||
ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid pointer", type, readBufPtr, readBufSize, idCountPtr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < std::min((size_t)readBufSize, threadqueue.size()); i++)
|
||||
{
|
||||
Memory::Write_U32(threadqueue[i], readBufPtr + (u32)i * 4);
|
||||
u32 total = 0;
|
||||
auto uids = PSPPointer<SceUID>::Create(readBufPtr);
|
||||
u32 error;
|
||||
if (type > 0 && type <= SCE_KERNEL_TMID_Tlspl) {
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", type, readBufPtr, readBufSize, idCountPtr);
|
||||
total = kernelObjects.ListIDType(type, uids, readBufSize);
|
||||
} else if (type >= SCE_KERNEL_TMID_SleepThread && type <= SCE_KERNEL_TMID_DormantThread) {
|
||||
bool (*checkFunc)(const Thread *t) = NULL;
|
||||
switch (type) {
|
||||
case SCE_KERNEL_TMID_SleepThread:
|
||||
checkFunc = &__ThreadmanIdListIsSleeping;
|
||||
break;
|
||||
|
||||
case SCE_KERNEL_TMID_DelayThread:
|
||||
checkFunc = &__ThreadmanIdListIsDelayed;
|
||||
break;
|
||||
|
||||
case SCE_KERNEL_TMID_SuspendThread:
|
||||
checkFunc = &__ThreadmanIdListIsSuspended;
|
||||
break;
|
||||
|
||||
case SCE_KERNEL_TMID_DormantThread:
|
||||
checkFunc = &__ThreadmanIdListIsDormant;
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(SCEKERNEL, false, "Unexpected type %d", type);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < threadqueue.size(); i++) {
|
||||
const Thread *t = kernelObjects.Get<Thread>(threadqueue[i], error);
|
||||
if (checkFunc(t)) {
|
||||
if (total < readBufSize) {
|
||||
*uids++ = threadqueue[i];
|
||||
}
|
||||
++total;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid type", type, readBufPtr, readBufSize, idCountPtr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_TYPE;
|
||||
}
|
||||
Memory::Write_U32((u32)threadqueue.size(), idCountPtr);
|
||||
return 0;
|
||||
|
||||
if (Memory::IsValidAddress(idCountPtr)) {
|
||||
Memory::Write_U32(total, idCountPtr);
|
||||
}
|
||||
return total > readBufSize ? readBufSize : total;
|
||||
}
|
||||
|
||||
// Saves the current CPU context
|
||||
@@ -3132,21 +3195,21 @@ void Thread::resumeFromWait()
|
||||
isProcessingCallbacks = false;
|
||||
}
|
||||
|
||||
bool Thread::isWaitingFor(WaitType type, int id)
|
||||
bool Thread::isWaitingFor(WaitType type, int id) const
|
||||
{
|
||||
if (nt.status & THREADSTATUS_WAIT)
|
||||
return nt.waitType == type && nt.waitID == id;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Thread::getWaitID(WaitType type)
|
||||
int Thread::getWaitID(WaitType type) const
|
||||
{
|
||||
if (nt.waitType == type)
|
||||
return nt.waitID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadWaitInfo Thread::getWaitInfo()
|
||||
ThreadWaitInfo Thread::getWaitInfo() const
|
||||
{
|
||||
return waitInfo;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user