Run callbacks in creation order, not notify order.

This commit is contained in:
Unknown W. Brackets committed 2013-09-09 00:21:59 -07:00
1 parent 87bd8d59e2
commit 4bba276696
1 file changed
+60 -48
+60 -48
View File
@@ -498,7 +498,7 @@ public:
p.Do(currentCallbackId);
p.Do(context);
p.Do(readyCallbacks);
p.Do(callbacks);
p.Do(pendingMipsCalls);
p.Do(pushedStacks);
@@ -518,7 +518,7 @@ public:
ThreadContext context;
std::list<SceUID> readyCallbacks;
std::vector<SceUID> callbacks;
std::list<u32> pendingMipsCalls;
@@ -1750,7 +1750,14 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason)
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
readyCallbacksCount -= (int)t->readyCallbacks.size();
{
for (auto it = t->callbacks.begin(), end = t->callbacks.end(); it != end; ++it)
{
Callback *callback = kernelObjects.Get<Callback>(*it, error);
if (callback && callback->nc.notifyCount != 0)
readyCallbacksCount--;
}
}
return kernelObjects.Destroy<Thread>(threadID);
}
@@ -2810,6 +2817,10 @@ SceUID sceKernelCreateCallback(const char *name, u32 entrypoint, u32 signalArg)
cb->nc.notifyCount = 0;
cb->nc.notifyArg = 0;
Thread *thread = __GetCurrentThread();
if (thread)
thread->callbacks.push_back(id);
DEBUG_LOG(SCEKERNEL, "%i=sceKernelCreateCallback(name=%s, entry=%08x, callbackArg=%08x)", id, name, entrypoint, signalArg);
return id;
@@ -2819,9 +2830,19 @@ int sceKernelDeleteCallback(SceUID cbId)
{
DEBUG_LOG(SCEKERNEL, "sceKernelDeleteCallback(%i)", cbId);
// TODO: Make sure it's gone from all threads first!
u32 error;
Callback *cb = kernelObjects.Get<Callback>(cbId, error);
if (cb)
{
Thread *thread = kernelObjects.Get<Thread>(cb->nc.threadId, error);
if (thread)
thread->callbacks.erase(std::find(thread->callbacks.begin(), thread->callbacks.end(), cbId), thread->callbacks.end());
if (cb->nc.notifyCount != 0)
readyCallbacksCount--;
return kernelObjects.Destroy<Callback>(cbId);
return kernelObjects.Destroy<Callback>(cbId);
}
return error;
}
// Generally very rarely used, but Numblast uses it like candy.
@@ -3421,38 +3442,37 @@ void ActionAfterCallback::run(MipsCall &call) {
}
bool __KernelCurHasReadyCallbacks() {
if (readyCallbacksCount == 0)
if (readyCallbacksCount == 0) {
return false;
Thread *thread = __GetCurrentThread();
if (thread->readyCallbacks.size()) {
return true;
}
Thread *thread = __GetCurrentThread();
u32 error;
for (auto it = thread->callbacks.begin(), end = thread->callbacks.end(); it != end; ++it) {
Callback *callback = kernelObjects.Get<Callback>(*it, error);
if (callback && callback->nc.notifyCount != 0) {
return true;
}
}
return false;
}
// Check callbacks on the current thread only.
// Returns true if any callbacks were processed on the current thread.
bool __KernelCheckThreadCallbacks(Thread *thread, bool force)
{
if (!thread || (!thread->isProcessingCallbacks && !force))
bool __KernelCheckThreadCallbacks(Thread *thread, bool force) {
if (!thread || (!thread->isProcessingCallbacks && !force)) {
return false;
}
if (thread->readyCallbacks.size()) {
SceUID readyCallback = thread->readyCallbacks.front();
thread->readyCallbacks.pop_front();
readyCallbacksCount--;
// If the callback was deleted, we're good. Just skip it.
if (kernelObjects.IsValid(readyCallback))
{
__KernelRunCallbackOnThread(readyCallback, thread, !force); // makes pending
return true;
}
else
{
WARN_LOG(SCEKERNEL, "Ignoring deleted callback %08x", readyCallback);
if (!thread->callbacks.empty()) {
u32 error;
for (auto it = thread->callbacks.begin(), end = thread->callbacks.end(); it != end; ++it) {
Callback *callback = kernelObjects.Get<Callback>(*it, error);
if (callback && callback->nc.notifyCount != 0) {
__KernelRunCallbackOnThread(callback->GetUID(), thread, !force);
readyCallbacksCount--;
return true;
}
}
}
return false;
@@ -3468,23 +3488,20 @@ bool __KernelCheckCallbacks() {
ERROR_LOG_REPORT(SCEKERNEL, "readyCallbacksCount became negative: %i", readyCallbacksCount);
}
// SceUID currentThread = __KernelGetCurThread();
// __GetCurrentThread()->isProcessingCallbacks = true;
// do {
bool processed = false;
bool processed = false;
u32 error;
for (std::vector<SceUID>::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) {
Thread *thread = kernelObjects.Get<Thread>(*iter, error);
if (thread && __KernelCheckThreadCallbacks(thread, false)) {
processed = true;
}
u32 error;
for (std::vector<SceUID>::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) {
Thread *thread = kernelObjects.Get<Thread>(*iter, error);
if (thread && __KernelCheckThreadCallbacks(thread, false)) {
processed = true;
}
// } while (processed && currentThread == __KernelGetCurThread());
}
if (processed)
if (processed) {
return __KernelExecutePendingMipsCalls(__GetCurrentThread(), true);
return processed;
}
return false;
}
bool __KernelForceCallbacks()
@@ -3536,16 +3553,11 @@ void __KernelNotifyCallback(SceUID cbId, int notifyArg)
ERROR_LOG(SCEKERNEL, "__KernelNotifyCallback - invalid callback %08x", cbId);
return;
}
cb->nc.notifyCount++;
cb->nc.notifyArg = notifyArg;
Thread *t = kernelObjects.Get<Thread>(cb->nc.threadId, error);
auto iter = std::find(t->readyCallbacks.begin(), t->readyCallbacks.end(), cbId);
if (iter == t->readyCallbacks.end())
{
t->readyCallbacks.push_back(cbId);
if (cb->nc.notifyCount == 0) {
readyCallbacksCount++;
}
cb->nc.notifyCount++;
cb->nc.notifyArg = notifyArg;
}
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc)