Keep a single list of pending callbacks.

Doing it per type only meant that we'd incorrectly call a callback twice
if it was notified by e.g. scePowerRegisterCallback() and
sceKernelNotifyThread(), which isn't what's supposed to happen.
This commit is contained in:
Unknown W. Brackets 2013-09-02 01:05:55 -07:00
parent 74418c13bf
commit 94e88943d8

View file

@ -510,8 +510,8 @@ public:
for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i) for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i)
{ {
p.Do(registeredCallbacks[i]); p.Do(registeredCallbacks[i]);
p.Do(readyCallbacks[i]);
} }
p.Do(readyCallbacks);
p.Do(pendingMipsCalls); p.Do(pendingMipsCalls);
p.Do(pushedStacks); p.Do(pushedStacks);
@ -532,7 +532,7 @@ public:
ThreadContext context; ThreadContext context;
std::set<SceUID> registeredCallbacks[THREAD_CALLBACK_NUM_TYPES]; std::set<SceUID> registeredCallbacks[THREAD_CALLBACK_NUM_TYPES];
std::list<SceUID> readyCallbacks[THREAD_CALLBACK_NUM_TYPES]; std::list<SceUID> readyCallbacks;
std::list<u32> pendingMipsCalls; std::list<u32> pendingMipsCalls;
@ -1764,11 +1764,7 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason)
u32 error; u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error); Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t) if (t)
{ readyCallbacksCount -= (int)t->readyCallbacks.size();
// TODO: Unless they should be run before deletion?
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++)
readyCallbacksCount -= (int)t->readyCallbacks[i].size();
}
return kernelObjects.Destroy<Thread>(threadID); return kernelObjects.Destroy<Thread>(threadID);
} }
@ -3444,11 +3440,9 @@ bool __KernelCurHasReadyCallbacks() {
return false; return false;
Thread *thread = __GetCurrentThread(); Thread *thread = __GetCurrentThread();
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) { if (thread->readyCallbacks.size()) {
if (thread->readyCallbacks[i].size()) {
return true; return true;
} }
}
return false; return false;
} }
@ -3460,10 +3454,9 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force)
if (!thread || (!thread->isProcessingCallbacks && !force)) if (!thread || (!thread->isProcessingCallbacks && !force))
return false; return false;
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) { if (thread->readyCallbacks.size()) {
if (thread->readyCallbacks[i].size()) { SceUID readyCallback = thread->readyCallbacks.front();
SceUID readyCallback = thread->readyCallbacks[i].front(); thread->readyCallbacks.pop_front();
thread->readyCallbacks[i].pop_front();
readyCallbacksCount--; readyCallbacksCount--;
// If the callback was deleted, we're good. Just skip it. // If the callback was deleted, we're good. Just skip it.
@ -3477,7 +3470,6 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force)
WARN_LOG(SCEKERNEL, "Ignoring deleted callback %08x", readyCallback); WARN_LOG(SCEKERNEL, "Ignoring deleted callback %08x", readyCallback);
} }
} }
}
return false; return false;
} }
@ -3586,11 +3578,10 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notify
cb->nc.notifyArg = notifyArg; cb->nc.notifyArg = notifyArg;
Thread *t = kernelObjects.Get<Thread>(cb->nc.threadId, error); Thread *t = kernelObjects.Get<Thread>(cb->nc.threadId, error);
std::list<SceUID> &readyCallbacks = t->readyCallbacks[type]; auto iter = std::find(t->readyCallbacks.begin(), t->readyCallbacks.end(), cbId);
auto iter = std::find(readyCallbacks.begin(), readyCallbacks.end(), cbId); if (iter == t->readyCallbacks.end())
if (iter == readyCallbacks.end())
{ {
t->readyCallbacks[type].push_back(cbId); t->readyCallbacks.push_back(cbId);
readyCallbacksCount++; readyCallbacksCount++;
} }
} }