Refactor waiting thread cleanup.

This commit is contained in:
Unknown W. Brackets 2013-09-08 21:29:39 -07:00
parent 1040123a97
commit 4bd391b098
7 changed files with 37 additions and 65 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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