mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Refactor waiting thread cleanup.
This commit is contained in:
parent
1040123a97
commit
4bd391b098
@ -259,7 +259,17 @@ WaitBeginEndCallbackResult WaitEndCallback(SceUID threadID, SceUID prevCallbackI
|
||||
}
|
||||
|
||||
// Verify that a thread has not been released from waiting, e.g. by sceKernelReleaseWaitThread().
|
||||
inline bool VerifyWait(SceUID threadID, WaitType waitType, SceUID uid) {
|
||||
// For a waiting thread info struct.
|
||||
template <typename T>
|
||||
inline bool VerifyWait(const T &waitInfo, WaitType waitType, SceUID uid) {
|
||||
u32 error;
|
||||
SceUID waitID = __KernelGetWaitID(waitInfo.threadID, waitType, error);
|
||||
return waitID == uid && error == 0;
|
||||
}
|
||||
|
||||
// Verify that a thread has not been released from waiting, e.g. by sceKernelReleaseWaitThread().
|
||||
template <>
|
||||
inline bool VerifyWait(const SceUID &threadID, WaitType waitType, SceUID uid) {
|
||||
u32 error;
|
||||
SceUID waitID = __KernelGetWaitID(threadID, waitType, error);
|
||||
return waitID == uid && error == 0;
|
||||
@ -275,4 +285,21 @@ inline bool ResumeFromWait(SceUID threadID, WaitType waitType, SceUID uid, T res
|
||||
return false;
|
||||
}
|
||||
|
||||
// Removes threads that are not waiting anymore from a waitingThreads list.
|
||||
template <typename T>
|
||||
inline void CleanupWaitingThreads(WaitType waitType, SceUID uid, std::vector<T> &waitingThreads) {
|
||||
size_t size = waitingThreads.size();
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (!VerifyWait(waitingThreads[i], waitType, uid)) {
|
||||
// Decrement size and swap what was there with i.
|
||||
if (--size != i) {
|
||||
std::swap(waitingThreads[i], waitingThreads[size]);
|
||||
}
|
||||
// Now we haven't checked the new i, so go back and do i again.
|
||||
--i;
|
||||
}
|
||||
}
|
||||
waitingThreads.resize(size);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -622,12 +622,7 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr)
|
||||
if (!Memory::IsValidAddress(statusPtr))
|
||||
return -1;
|
||||
|
||||
for (auto iter = e->waitingThreads.begin(); iter != e->waitingThreads.end(); ++iter)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(iter->threadID, WAITTYPE_EVENTFLAG, id))
|
||||
e->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_EVENTFLAG, id, e->waitingThreads);
|
||||
|
||||
e->nef.numWaitThreads = (int) e->waitingThreads.size();
|
||||
if (Memory::Read_U32(statusPtr) != 0)
|
||||
|
@ -583,12 +583,7 @@ int sceKernelReferMbxStatus(SceUID id, u32 infoAddr)
|
||||
for (int i = 0, n = m->nmb.numMessages; i < n; ++i)
|
||||
m->nmb.packetListHead = Memory::Read_U32(m->nmb.packetListHead);
|
||||
|
||||
for (auto iter = m->waitingThreads.begin(); iter != m->waitingThreads.end(); ++iter)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(iter->threadID, WAITTYPE_MBX, id))
|
||||
m->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_MBX, id, m->waitingThreads);
|
||||
|
||||
// For whatever reason, it won't write if the size (first member) is 0.
|
||||
if (Memory::Read_U32(infoAddr) != 0)
|
||||
|
@ -325,14 +325,7 @@ void __KernelSortFplThreads(FPL *fpl)
|
||||
{
|
||||
// Remove any that are no longer waiting.
|
||||
SceUID uid = fpl->GetUID();
|
||||
for (size_t i = 0; i < fpl->waitingThreads.size(); i++)
|
||||
{
|
||||
if (!HLEKernel::VerifyWait(fpl->waitingThreads[i].threadID, WAITTYPE_FPL, uid))
|
||||
{
|
||||
fpl->waitingThreads.erase(fpl->waitingThreads.begin() + i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_FPL, uid, fpl->waitingThreads);
|
||||
|
||||
if ((fpl->nf.attr & PSP_FPL_ATTR_PRIORITY) != 0)
|
||||
std::stable_sort(fpl->waitingThreads.begin(), fpl->waitingThreads.end(), __FplThreadSortPriority);
|
||||
@ -1212,14 +1205,7 @@ void __KernelSortFplThreads(VPL *vpl)
|
||||
{
|
||||
// Remove any that are no longer waiting.
|
||||
SceUID uid = vpl->GetUID();
|
||||
for (size_t i = 0; i < vpl->waitingThreads.size(); i++)
|
||||
{
|
||||
if (!HLEKernel::VerifyWait(vpl->waitingThreads[i].threadID, WAITTYPE_VPL, uid))
|
||||
{
|
||||
vpl->waitingThreads.erase(vpl->waitingThreads.begin() + i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_VPL, uid, vpl->waitingThreads);
|
||||
|
||||
if ((vpl->nv.attr & PSP_VPL_ATTR_PRIORITY) != 0)
|
||||
std::stable_sort(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), __VplThreadSortPriority);
|
||||
|
@ -241,18 +241,7 @@ struct MsgPipe : public KernelObject
|
||||
void SortThreads(std::vector<MsgPipeWaitingThread> &waitingThreads, bool usePrio)
|
||||
{
|
||||
// Clean up any not waiting at the same time.
|
||||
size_t size = waitingThreads.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (!waitingThreads[i].IsStillWaiting(GetUID()))
|
||||
{
|
||||
// Decrement size and swap what was there with i.
|
||||
std::swap(waitingThreads[i], waitingThreads[--size]);
|
||||
// Now we haven't checked the new i, so go back and do i again.
|
||||
--i;
|
||||
}
|
||||
}
|
||||
waitingThreads.resize(size);
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_MSGPIPE, GetUID(), waitingThreads);
|
||||
|
||||
if (usePrio)
|
||||
std::stable_sort(waitingThreads.begin(), waitingThreads.end(), __KernelMsgPipeThreadSortPriority);
|
||||
|
@ -517,12 +517,7 @@ int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr)
|
||||
DEBUG_LOG(SCEKERNEL, "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)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(*iter, WAITTYPE_MUTEX, uid))
|
||||
mutex->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_MUTEX, uid, mutex->waitingThreads);
|
||||
|
||||
if (Memory::IsValidAddress(numWaitThreadsPtr))
|
||||
Memory::Write_U32((u32)mutex->waitingThreads.size(), numWaitThreadsPtr);
|
||||
@ -682,12 +677,7 @@ int sceKernelReferMutexStatus(SceUID id, u32 infoAddr)
|
||||
// Don't write if the size is 0. Anything else is A-OK, though, apparently.
|
||||
if (Memory::Read_U32(infoAddr) != 0)
|
||||
{
|
||||
for (auto iter = m->waitingThreads.begin(); iter != m->waitingThreads.end(); ++iter)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(*iter, WAITTYPE_MUTEX, id))
|
||||
m->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_MUTEX, id, m->waitingThreads);
|
||||
|
||||
m->nm.numWaitThreads = (int) m->waitingThreads.size();
|
||||
Memory::WriteStruct(infoAddr, &m->nm);
|
||||
@ -1065,12 +1055,7 @@ int __KernelReferLwMutexStatus(SceUID uid, u32 infoPtr)
|
||||
{
|
||||
auto workarea = m->nm.workarea;
|
||||
|
||||
for (auto iter = m->waitingThreads.begin(); iter != m->waitingThreads.end(); ++iter)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(*iter, WAITTYPE_LWMUTEX, uid))
|
||||
m->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_LWMUTEX, uid, m->waitingThreads);
|
||||
|
||||
// Refresh and write
|
||||
m->nm.currentCount = workarea->lockLevel;
|
||||
|
@ -266,12 +266,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
|
||||
if (!Memory::IsValidAddress(infoPtr))
|
||||
return -1;
|
||||
|
||||
for (auto iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter)
|
||||
{
|
||||
// The thread is no longer waiting for this, clean it up.
|
||||
if (!HLEKernel::VerifyWait(*iter, WAITTYPE_SEMA, id))
|
||||
s->waitingThreads.erase(iter--);
|
||||
}
|
||||
HLEKernel::CleanupWaitingThreads(WAITTYPE_SEMA, id, s->waitingThreads);
|
||||
|
||||
s->ns.numWaitThreads = (int) s->waitingThreads.size();
|
||||
if (Memory::Read_U32(infoPtr) != 0)
|
||||
|
Loading…
Reference in New Issue
Block a user