mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-12 22:10:29 +02:00
Run callbacks in creation order, not notify order.
This commit is contained in:
1 parent
87bd8d59e2
commit
4bba276696
1 file changed
+60
-48
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user