mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-10 04:56:24 +02:00
Merge pull request #3700 from unknownbrackets/callbacks
Improve callbacks (still not rescheduling properly inside one)
This commit is contained in:
commit
628f77e2b0
13 files changed
+171
-301
No files matched your search
@@ -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,26 @@ 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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void RemoveWaitingThread(std::vector<T> &waitingThreads, const SceUID threadID) {
|
||||
waitingThreads.erase(std::remove(waitingThreads.begin(), waitingThreads.end(), threadID), waitingThreads.end());
|
||||
}
|
||||
|
||||
};
|
||||
+23
-7
@@ -16,6 +16,7 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
#include "native/thread/thread.h"
|
||||
#include "native/thread/threadutil.h"
|
||||
#include "Core/Config.h"
|
||||
@@ -108,6 +109,8 @@ const int PSP_MIN_FD = 4;
|
||||
static int asyncNotifyEvent = -1;
|
||||
static int syncNotifyEvent = -1;
|
||||
static SceUID fds[PSP_COUNT_FDS];
|
||||
static std::set<SceUID> memStickCallbacks;
|
||||
static std::set<SceUID> memStickFatCallbacks;
|
||||
static AsyncIOManager ioManager;
|
||||
static bool ioManagerThreadEnabled = false;
|
||||
static std::thread *ioManagerThread;
|
||||
@@ -466,6 +469,8 @@ void __IoDoState(PointerWrap &p) {
|
||||
CoreTiming::RestoreRegisterEvent(asyncNotifyEvent, "IoAsyncNotify", __IoAsyncNotify);
|
||||
p.Do(syncNotifyEvent);
|
||||
CoreTiming::RestoreRegisterEvent(syncNotifyEvent, "IoSyncNotify", __IoSyncNotify);
|
||||
p.Do(memStickCallbacks);
|
||||
p.Do(memStickFatCallbacks);
|
||||
p.DoMarker("sceIo");
|
||||
}
|
||||
|
||||
@@ -487,6 +492,9 @@ void __IoShutdown() {
|
||||
memstickSystem = NULL;
|
||||
delete flash0System;
|
||||
flash0System = NULL;
|
||||
|
||||
memStickCallbacks.clear();
|
||||
memStickFatCallbacks.clear();
|
||||
}
|
||||
|
||||
u32 __IoGetFileHandleFromId(u32 id, u32 &outError)
|
||||
@@ -552,7 +560,7 @@ void __IoCompleteAsyncIO(int fd) {
|
||||
// It's okay, not all operations are deferred.
|
||||
}
|
||||
if (f->callbackID) {
|
||||
__KernelNotifyCallback(THREAD_CALLBACK_IO, f->callbackID, f->callbackArg);
|
||||
__KernelNotifyCallback(f->callbackID, f->callbackArg);
|
||||
}
|
||||
f->pendingAsyncResult = false;
|
||||
f->hasAsyncResult = true;
|
||||
@@ -1262,10 +1270,12 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
case 0x02015804:
|
||||
// Register MemoryStick's insert/eject callback (mscmhc0)
|
||||
if (Memory::IsValidAddress(argAddr) && argLen == 4) {
|
||||
// TODO: Verify how duplicates work / how many are allowed.
|
||||
u32 cbId = Memory::Read_U32(argAddr);
|
||||
if (0 == __KernelRegisterCallback(THREAD_CALLBACK_MEMORYSTICK, cbId)) {
|
||||
if (memStickCallbacks.find(cbId) == memStickCallbacks.end()) {
|
||||
memStickCallbacks.insert(cbId);
|
||||
DEBUG_LOG(SCEIO, "sceIoDevCtl: Memstick callback %i registered, notifying immediately.", cbId);
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_MEMORYSTICK, cbId, MemoryStick_State());
|
||||
__KernelNotifyCallback(cbId, MemoryStick_State());
|
||||
return 0;
|
||||
} else {
|
||||
return ERROR_MEMSTICK_DEVCTL_TOO_MANY_CALLBACKS;
|
||||
@@ -1277,8 +1287,10 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
case 0x02025805:
|
||||
// Unregister MemoryStick's insert/eject callback (mscmhc0)
|
||||
if (Memory::IsValidAddress(argAddr) && argLen == 4) {
|
||||
// TODO: Verify how duplicates work / how many are allowed.
|
||||
u32 cbId = Memory::Read_U32(argAddr);
|
||||
if (0 == __KernelUnregisterCallback(THREAD_CALLBACK_MEMORYSTICK, cbId)) {
|
||||
if (memStickCallbacks.find(cbId) != memStickCallbacks.end()) {
|
||||
memStickCallbacks.erase(cbId);
|
||||
DEBUG_LOG(SCEIO, "sceIoDevCtl: Unregistered memstick callback %i", cbId);
|
||||
return 0;
|
||||
} else {
|
||||
@@ -1337,10 +1349,12 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
switch (cmd) {
|
||||
case 0x02415821: // MScmRegisterMSInsertEjectCallback
|
||||
{
|
||||
// TODO: Verify how duplicates work / how many are allowed.
|
||||
u32 cbId = Memory::Read_U32(argAddr);
|
||||
if (0 == __KernelRegisterCallback(THREAD_CALLBACK_MEMORYSTICK_FAT, cbId)) {
|
||||
if (memStickFatCallbacks.find(cbId) == memStickFatCallbacks.end()) {
|
||||
memStickFatCallbacks.insert(cbId);
|
||||
DEBUG_LOG(SCEIO, "sceIoDevCtl: Memstick FAT callback %i registered, notifying immediately.", cbId);
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_MEMORYSTICK_FAT, cbId, MemoryStick_FatState());
|
||||
__KernelNotifyCallback(cbId, MemoryStick_FatState());
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
@@ -1350,8 +1364,10 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
case 0x02415822:
|
||||
{
|
||||
// MScmUnregisterMSInsertEjectCallback
|
||||
// TODO: Verify how duplicates work / how many are allowed.
|
||||
u32 cbId = Memory::Read_U32(argAddr);
|
||||
if (0 == __KernelUnregisterCallback(THREAD_CALLBACK_MEMORYSTICK_FAT, cbId)) {
|
||||
if (memStickFatCallbacks.find(cbId) != memStickFatCallbacks.end()) {
|
||||
memStickFatCallbacks.erase(cbId);
|
||||
DEBUG_LOG(SCEIO, "sceIoDevCtl: Unregistered memstick FAT callback %i", cbId);
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
static bool kernelRunning = false;
|
||||
KernelObjectPool kernelObjects;
|
||||
KernelStats kernelStats;
|
||||
// TODO: Savestate this?
|
||||
u32 registeredExitCbId;
|
||||
|
||||
void __KernelInit()
|
||||
@@ -261,10 +262,8 @@ int LoadExecForUser_362A956B()
|
||||
|
||||
u32 sceKernelRegisterExitCallback(u32 cbId)
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelRegisterExitCallback(%i)", cbId);
|
||||
if (__KernelRegisterCallback(THREAD_CALLBACK_EXIT, cbId) == 0) {
|
||||
registeredExitCbId = cbId;
|
||||
}
|
||||
DEBUG_LOG(SCEKERNEL,"sceKernelRegisterExitCallback(%i)", cbId);
|
||||
registeredExitCbId = cbId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,11 @@ struct EventFlagTh
|
||||
u32 wait;
|
||||
u32 outAddr;
|
||||
u64 pausedTimeout;
|
||||
|
||||
bool operator ==(const SceUID &otherThreadID) const
|
||||
{
|
||||
return threadID == otherThreadID;
|
||||
}
|
||||
};
|
||||
|
||||
class EventFlag : public KernelObject
|
||||
@@ -397,19 +402,6 @@ void __KernelSetEventFlagTimeout(EventFlag *e, u32 timeoutPtr)
|
||||
CoreTiming::ScheduleEvent(usToCycles(micro), eventFlagWaitTimer, __KernelGetCurThread());
|
||||
}
|
||||
|
||||
void __KernelEventFlagRemoveThread(EventFlag *e, SceUID threadID)
|
||||
{
|
||||
for (size_t i = 0; i < e->waitingThreads.size(); i++)
|
||||
{
|
||||
EventFlagTh *t = &e->waitingThreads[i];
|
||||
if (t->threadID == threadID)
|
||||
{
|
||||
e->waitingThreads.erase(e->waitingThreads.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr)
|
||||
{
|
||||
if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
|
||||
@@ -439,7 +431,7 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti
|
||||
{
|
||||
// If this thread was left in waitingThreads after a timeout, remove it.
|
||||
// Otherwise we might write the outBitsPtr in the wrong place.
|
||||
__KernelEventFlagRemoveThread(e, __KernelGetCurThread());
|
||||
HLEKernel::RemoveWaitingThread(e->waitingThreads, __KernelGetCurThread());
|
||||
|
||||
u32 timeout = 0xFFFFFFFF;
|
||||
if (Memory::IsValidAddress(timeoutPtr))
|
||||
@@ -514,7 +506,7 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32
|
||||
{
|
||||
// If this thread was left in waitingThreads after a timeout, remove it.
|
||||
// Otherwise we might write the outBitsPtr in the wrong place.
|
||||
__KernelEventFlagRemoveThread(e, __KernelGetCurThread());
|
||||
HLEKernel::RemoveWaitingThread(e->waitingThreads, __KernelGetCurThread());
|
||||
|
||||
u32 timeout = 0xFFFFFFFF;
|
||||
if (Memory::IsValidAddress(timeoutPtr))
|
||||
@@ -622,12 +614,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)
|
||||
|
||||
@@ -37,6 +37,11 @@ struct MbxWaitingThread
|
||||
SceUID threadID;
|
||||
u32 packetAddr;
|
||||
u64 pausedTimeout;
|
||||
|
||||
bool operator ==(const SceUID &otherThreadID) const
|
||||
{
|
||||
return threadID == otherThreadID;
|
||||
}
|
||||
};
|
||||
void __KernelMbxTimeout(u64 userdata, int cyclesLate);
|
||||
|
||||
@@ -274,19 +279,6 @@ void __KernelWaitMbx(Mbx *m, u32 timeoutPtr)
|
||||
CoreTiming::ScheduleEvent(usToCycles(micro), mbxWaitTimer, __KernelGetCurThread());
|
||||
}
|
||||
|
||||
void __KernelMbxRemoveThread(Mbx *m, SceUID threadID)
|
||||
{
|
||||
for (size_t i = 0; i < m->waitingThreads.size(); i++)
|
||||
{
|
||||
MbxWaitingThread *t = &m->waitingThreads[i];
|
||||
if (t->threadID == threadID)
|
||||
{
|
||||
m->waitingThreads.erase(m->waitingThreads.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MbxWaitingThread>::iterator __KernelMbxFindPriority(std::vector<MbxWaitingThread> &waiting)
|
||||
{
|
||||
_dbg_assert_msg_(SCEKERNEL, !waiting.empty(), "__KernelMutexFindPriority: Trying to find best of no threads.");
|
||||
@@ -480,7 +472,7 @@ int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr)
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbx(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr);
|
||||
__KernelMbxRemoveThread(m, __KernelGetCurThread());
|
||||
HLEKernel::RemoveWaitingThread(m->waitingThreads, __KernelGetCurThread());
|
||||
m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr);
|
||||
__KernelWaitMbx(m, timeoutPtr);
|
||||
__KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, false, "mbx waited");
|
||||
@@ -508,7 +500,7 @@ int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr)
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbxCB(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr);
|
||||
__KernelMbxRemoveThread(m, __KernelGetCurThread());
|
||||
HLEKernel::RemoveWaitingThread(m->waitingThreads, __KernelGetCurThread());
|
||||
m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr);
|
||||
__KernelWaitMbx(m, timeoutPtr);
|
||||
__KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, true, "mbx waited");
|
||||
@@ -583,12 +575,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)
|
||||
|
||||
@@ -57,6 +57,11 @@ struct FplWaitingThread
|
||||
SceUID threadID;
|
||||
u32 addrPtr;
|
||||
u64 pausedTimeout;
|
||||
|
||||
bool operator ==(const SceUID &otherThreadID) const
|
||||
{
|
||||
return threadID == otherThreadID;
|
||||
}
|
||||
};
|
||||
|
||||
struct NativeFPL
|
||||
@@ -141,6 +146,11 @@ struct VplWaitingThread
|
||||
SceUID threadID;
|
||||
u32 addrPtr;
|
||||
u64 pausedTimeout;
|
||||
|
||||
bool operator ==(const SceUID &otherThreadID) const
|
||||
{
|
||||
return threadID == otherThreadID;
|
||||
}
|
||||
};
|
||||
|
||||
struct SceKernelVplInfo
|
||||
@@ -292,19 +302,6 @@ void __KernelFplEndCallback(SceUID threadID, SceUID prevCallbackId)
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbxCB: Resuming mbx wait from callback");
|
||||
}
|
||||
|
||||
void __KernelFplRemoveThread(FPL *fpl, SceUID threadID)
|
||||
{
|
||||
for (size_t i = 0; i < fpl->waitingThreads.size(); i++)
|
||||
{
|
||||
FplWaitingThread *t = &fpl->waitingThreads[i];
|
||||
if (t->threadID == threadID)
|
||||
{
|
||||
fpl->waitingThreads.erase(fpl->waitingThreads.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool __FplThreadSortPriority(FplWaitingThread thread1, FplWaitingThread thread2)
|
||||
{
|
||||
return __KernelThreadSortPriority(thread1.threadID, thread2.threadID);
|
||||
@@ -325,14 +322,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);
|
||||
@@ -489,7 +479,7 @@ int sceKernelAllocateFpl(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr)
|
||||
Memory::Write_U32(blockPtr, blockPtrAddr);
|
||||
} else {
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
__KernelFplRemoveThread(fpl, threadID);
|
||||
HLEKernel::RemoveWaitingThread(fpl->waitingThreads, threadID);
|
||||
FplWaitingThread waiting = {threadID, blockPtrAddr};
|
||||
fpl->waitingThreads.push_back(waiting);
|
||||
|
||||
@@ -520,7 +510,7 @@ int sceKernelAllocateFplCB(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr)
|
||||
Memory::Write_U32(blockPtr, blockPtrAddr);
|
||||
} else {
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
__KernelFplRemoveThread(fpl, threadID);
|
||||
HLEKernel::RemoveWaitingThread(fpl->waitingThreads, threadID);
|
||||
FplWaitingThread waiting = {threadID, blockPtrAddr};
|
||||
fpl->waitingThreads.push_back(waiting);
|
||||
|
||||
@@ -1179,19 +1169,6 @@ void __KernelVplEndCallback(SceUID threadID, SceUID prevCallbackId)
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbxCB: Resuming mbx wait from callback");
|
||||
}
|
||||
|
||||
void __KernelVplRemoveThread(VPL *vpl, SceUID threadID)
|
||||
{
|
||||
for (size_t i = 0; i < vpl->waitingThreads.size(); i++)
|
||||
{
|
||||
VplWaitingThread *t = &vpl->waitingThreads[i];
|
||||
if (t->threadID == threadID)
|
||||
{
|
||||
vpl->waitingThreads.erase(vpl->waitingThreads.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool __VplThreadSortPriority(VplWaitingThread thread1, VplWaitingThread thread2)
|
||||
{
|
||||
return __KernelThreadSortPriority(thread1.threadID, thread2.threadID);
|
||||
@@ -1212,14 +1189,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);
|
||||
@@ -1391,7 +1361,7 @@ int sceKernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
|
||||
if (vpl)
|
||||
{
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
__KernelVplRemoveThread(vpl, threadID);
|
||||
HLEKernel::RemoveWaitingThread(vpl->waitingThreads, threadID);
|
||||
VplWaitingThread waiting = {threadID, addrPtr};
|
||||
vpl->waitingThreads.push_back(waiting);
|
||||
}
|
||||
@@ -1416,7 +1386,7 @@ int sceKernelAllocateVplCB(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
|
||||
if (vpl)
|
||||
{
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
__KernelVplRemoveThread(vpl, threadID);
|
||||
HLEKernel::RemoveWaitingThread(vpl->waitingThreads, threadID);
|
||||
VplWaitingThread waiting = {threadID, addrPtr};
|
||||
vpl->waitingThreads.push_back(waiting);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -270,19 +259,14 @@ struct MsgPipe : public KernelObject
|
||||
SortThreads(sendWaitingThreads, usePrio);
|
||||
}
|
||||
|
||||
void RemoveWaitingThread(std::vector<MsgPipeWaitingThread> &waitingThreads, SceUID threadID)
|
||||
{
|
||||
waitingThreads.erase(std::remove(waitingThreads.begin(), waitingThreads.end(), threadID), waitingThreads.end());
|
||||
}
|
||||
|
||||
void RemoveReceiveWaitingThread(SceUID threadID)
|
||||
{
|
||||
RemoveWaitingThread(receiveWaitingThreads, threadID);
|
||||
HLEKernel::RemoveWaitingThread(receiveWaitingThreads, threadID);
|
||||
}
|
||||
|
||||
void RemoveSendWaitingThread(SceUID threadID)
|
||||
{
|
||||
RemoveWaitingThread(sendWaitingThreads, threadID);
|
||||
HLEKernel::RemoveWaitingThread(sendWaitingThreads, threadID);
|
||||
}
|
||||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
|
||||
@@ -461,7 +461,7 @@ void __KernelMutexThreadEnd(SceUID threadID)
|
||||
{
|
||||
Mutex *mutex = kernelObjects.Get<Mutex>(waitingMutexID, error);
|
||||
if (mutex)
|
||||
mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end());
|
||||
HLEKernel::RemoveWaitingThread(mutex->waitingThreads, threadID);
|
||||
}
|
||||
|
||||
// Unlock all mutexes the thread had locked.
|
||||
@@ -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)
|
||||
|
||||
+60
-111
@@ -464,6 +464,10 @@ public:
|
||||
|
||||
~Thread()
|
||||
{
|
||||
// Callbacks are automatically deleted when their owning thread is deleted.
|
||||
for (auto it = callbacks.begin(), end = callbacks.end(); it != end; ++it)
|
||||
kernelObjects.Destroy<Callback>(*it);
|
||||
|
||||
if (pushedStacks.size() != 0)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "Thread ended within an extended stack");
|
||||
@@ -498,20 +502,7 @@ public:
|
||||
p.Do(currentCallbackId);
|
||||
p.Do(context);
|
||||
|
||||
u32 numCallbacks = THREAD_CALLBACK_NUM_TYPES;
|
||||
p.Do(numCallbacks);
|
||||
if (numCallbacks != THREAD_CALLBACK_NUM_TYPES)
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(SCEKERNEL, "Unable to load state: different thread callback storage.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i)
|
||||
{
|
||||
p.Do(registeredCallbacks[i]);
|
||||
p.Do(readyCallbacks[i]);
|
||||
}
|
||||
p.Do(callbacks);
|
||||
|
||||
p.Do(pendingMipsCalls);
|
||||
p.Do(pushedStacks);
|
||||
@@ -531,8 +522,7 @@ public:
|
||||
|
||||
ThreadContext context;
|
||||
|
||||
std::set<SceUID> registeredCallbacks[THREAD_CALLBACK_NUM_TYPES];
|
||||
std::list<SceUID> readyCallbacks[THREAD_CALLBACK_NUM_TYPES];
|
||||
std::vector<SceUID> callbacks;
|
||||
|
||||
std::list<u32> pendingMipsCalls;
|
||||
|
||||
@@ -1765,9 +1755,12 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason)
|
||||
Thread *t = kernelObjects.Get<Thread>(threadID, error);
|
||||
if (t)
|
||||
{
|
||||
// TODO: Unless they should be run before deletion?
|
||||
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++)
|
||||
readyCallbacksCount -= (int)t->readyCallbacks[i].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);
|
||||
@@ -2828,6 +2821,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;
|
||||
@@ -2837,9 +2834,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.
|
||||
@@ -2849,8 +2856,7 @@ int sceKernelNotifyCallback(SceUID cbId, int notifyArg)
|
||||
u32 error;
|
||||
Callback *cb = kernelObjects.Get<Callback>(cbId, error);
|
||||
if (cb) {
|
||||
// TODO: Should this notify other existing callbacks too?
|
||||
__KernelNotifyCallback(THREAD_CALLBACK_USER_DEFINED, cbId, notifyArg);
|
||||
__KernelNotifyCallback(cbId, notifyArg);
|
||||
return 0;
|
||||
} else {
|
||||
ERROR_LOG(SCEKERNEL, "sceKernelCancelCallback(%i) - bad cbId", cbId);
|
||||
@@ -2988,7 +2994,7 @@ void ActionAfterMipsCall::run(MipsCall &call) {
|
||||
|
||||
ActionAfterMipsCall *Thread::getRunningCallbackAction()
|
||||
{
|
||||
if (this->GetUID() == currentThread && g_inCbCount > 0) {
|
||||
if (this->GetUID() == currentThread && g_inCbCount > 0) {
|
||||
MipsCall *call = mipsCalls.get(this->currentMipscallId);
|
||||
ActionAfterMipsCall *action = 0;
|
||||
if (call)
|
||||
@@ -3440,42 +3446,37 @@ void ActionAfterCallback::run(MipsCall &call) {
|
||||
}
|
||||
|
||||
bool __KernelCurHasReadyCallbacks() {
|
||||
if (readyCallbacksCount == 0)
|
||||
if (readyCallbacksCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Thread *thread = __GetCurrentThread();
|
||||
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) {
|
||||
if (thread->readyCallbacks[i].size()) {
|
||||
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;
|
||||
}
|
||||
|
||||
for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) {
|
||||
if (thread->readyCallbacks[i].size()) {
|
||||
SceUID readyCallback = thread->readyCallbacks[i].front();
|
||||
thread->readyCallbacks[i].pop_front();
|
||||
readyCallbacksCount--;
|
||||
|
||||
// If the callback was deleted, we're good. Just skip it.
|
||||
if (kernelObjects.IsValid(readyCallback))
|
||||
{
|
||||
__KernelRunCallbackOnThread(readyCallback, thread, !force); // makes pending
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN_LOG(SCEKERNEL, "Ignoring deleted callback %08x", readyCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -3491,23 +3492,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()
|
||||
@@ -3549,30 +3547,7 @@ bool __KernelInCallback()
|
||||
return (g_inCbCount != 0);
|
||||
}
|
||||
|
||||
|
||||
u32 __KernelRegisterCallback(RegisteredCallbackType type, SceUID cbId)
|
||||
{
|
||||
Thread *t = __GetCurrentThread();
|
||||
if (cbId > 0 && t->registeredCallbacks[type].find(cbId) == t->registeredCallbacks[type].end()) {
|
||||
t->registeredCallbacks[type].insert(cbId);
|
||||
return 0;
|
||||
} else {
|
||||
return SCE_KERNEL_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
u32 __KernelUnregisterCallback(RegisteredCallbackType type, SceUID cbId)
|
||||
{
|
||||
Thread *t = __GetCurrentThread();
|
||||
if (t->registeredCallbacks[type].find(cbId) != t->registeredCallbacks[type].end()) {
|
||||
t->registeredCallbacks[type].erase(cbId);
|
||||
return 0;
|
||||
} else {
|
||||
return 0x80010016;
|
||||
}
|
||||
}
|
||||
|
||||
void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg)
|
||||
void __KernelNotifyCallback(SceUID cbId, int notifyArg)
|
||||
{
|
||||
u32 error;
|
||||
|
||||
@@ -3582,37 +3557,11 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notify
|
||||
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);
|
||||
std::list<SceUID> &readyCallbacks = t->readyCallbacks[type];
|
||||
auto iter = std::find(readyCallbacks.begin(), readyCallbacks.end(), cbId);
|
||||
if (iter == readyCallbacks.end())
|
||||
{
|
||||
t->readyCallbacks[type].push_back(cbId);
|
||||
if (cb->nc.notifyCount == 0) {
|
||||
readyCallbacksCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: If cbId == -1, notify the callback ID on all threads that have it.
|
||||
u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int notifyArg)
|
||||
{
|
||||
u32 error;
|
||||
for (std::vector<SceUID>::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) {
|
||||
Thread *t = kernelObjects.Get<Thread>(*iter, error);
|
||||
if (!t)
|
||||
continue;
|
||||
|
||||
for (std::set<SceUID>::iterator citer = t->registeredCallbacks[type].begin(); citer != t->registeredCallbacks[type].end(); citer++) {
|
||||
if (cbId == -1 || cbId == *citer) {
|
||||
__KernelNotifyCallback(type, *citer, notifyArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkCallbacks on other threads?
|
||||
return 0;
|
||||
cb->nc.notifyCount++;
|
||||
cb->nc.notifyArg = notifyArg;
|
||||
}
|
||||
|
||||
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc)
|
||||
|
||||
@@ -173,27 +173,6 @@ void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue,
|
||||
void __KernelReSchedule(const char *reason = "no reason");
|
||||
void __KernelReSchedule(bool doCallbacks, const char *reason);
|
||||
|
||||
// Registered callback types
|
||||
enum RegisteredCallbackType {
|
||||
THREAD_CALLBACK_UMD = 0,
|
||||
THREAD_CALLBACK_IO = 1,
|
||||
THREAD_CALLBACK_MEMORYSTICK = 2,
|
||||
THREAD_CALLBACK_MEMORYSTICK_FAT = 3,
|
||||
THREAD_CALLBACK_POWER = 4,
|
||||
THREAD_CALLBACK_EXIT = 5,
|
||||
THREAD_CALLBACK_USER_DEFINED = 6,
|
||||
THREAD_CALLBACK_SIZE = 7,
|
||||
THREAD_CALLBACK_NUM_TYPES = 8,
|
||||
};
|
||||
|
||||
// These operate on the current thread
|
||||
u32 __KernelRegisterCallback(RegisteredCallbackType type, SceUID cbId);
|
||||
u32 __KernelUnregisterCallback(RegisteredCallbackType type, SceUID cbId);
|
||||
|
||||
// If cbId == -1, all the callbacks of the type on all the threads get notified.
|
||||
// If not, only this particular callback gets notified.
|
||||
u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int notifyArg);
|
||||
|
||||
SceUID __KernelGetCurThread();
|
||||
SceUID __KernelGetCurThreadModuleId();
|
||||
SceUID __KernelSetupRootThread(SceUID moduleId, int args, const char *argp, int prio, int stacksize, int attr); //represents the real PSP elf loader, run before execution
|
||||
@@ -232,7 +211,7 @@ bool __KernelCurHasReadyCallbacks();
|
||||
class Thread;
|
||||
void __KernelSwitchContext(Thread *target, const char *reason);
|
||||
bool __KernelExecutePendingMipsCalls(Thread *currentThread, bool reschedAfter);
|
||||
void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg);
|
||||
void __KernelNotifyCallback(SceUID cbId, int notifyArg);
|
||||
|
||||
// Switch to an idle / non-user thread, if not already on one.
|
||||
// Returns whether a switch occurred.
|
||||
|
||||
@@ -154,10 +154,8 @@ int scePowerRegisterCallback(int slot, int cbId) {
|
||||
}
|
||||
}
|
||||
if (retval >= 0) {
|
||||
__KernelRegisterCallback(THREAD_CALLBACK_POWER, cbId);
|
||||
|
||||
int arg = PSP_POWER_CB_AC_POWER | PSP_POWER_CB_BATTERY_EXIST | PSP_POWER_CB_BATTERY_FULL;
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_POWER, cbId, arg);
|
||||
__KernelNotifyCallback(cbId, arg);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -175,7 +173,6 @@ int scePowerUnregisterCallback(int slotId) {
|
||||
if (powerCbSlots[slotId] != 0) {
|
||||
int cbId = powerCbSlots[slotId];
|
||||
DEBUG_LOG(HLE, "0=scePowerUnregisterCallback(%i) (cbid = %i)", slotId, cbId);
|
||||
__KernelUnregisterCallback(THREAD_CALLBACK_POWER, cbId);
|
||||
powerCbSlots[slotId] = 0;
|
||||
} else {
|
||||
return PSP_POWER_ERROR_EMPTY_SLOT;
|
||||
|
||||
+10
-20
@@ -114,7 +114,8 @@ void __UmdStatChange(u64 userdata, int cyclesLate)
|
||||
void __KernelUmdActivate()
|
||||
{
|
||||
u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE;
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
|
||||
if (driveCBId != -1)
|
||||
__KernelNotifyCallback(driveCBId, notifyArg);
|
||||
|
||||
// Don't activate immediately, take time to "spin up."
|
||||
CoreTiming::RemoveAllEvents(umdStatChangeEvent);
|
||||
@@ -124,7 +125,8 @@ void __KernelUmdActivate()
|
||||
void __KernelUmdDeactivate()
|
||||
{
|
||||
u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READY;
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
|
||||
if (driveCBId != -1)
|
||||
__KernelNotifyCallback(driveCBId, notifyArg);
|
||||
|
||||
CoreTiming::RemoveAllEvents(umdStatChangeEvent);
|
||||
__UmdStatChange(0, 0);
|
||||
@@ -148,11 +150,7 @@ void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId)
|
||||
else
|
||||
umdPausedWaits[pauseKey] = 0;
|
||||
|
||||
for (auto it = umdWaitingThreads.begin(); it < umdWaitingThreads.end(); ++it)
|
||||
{
|
||||
if (*it == threadID)
|
||||
umdWaitingThreads.erase(it--);
|
||||
}
|
||||
HLEKernel::RemoveWaitingThread(umdWaitingThreads, threadID);
|
||||
|
||||
DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB: Suspending lock wait for callback");
|
||||
}
|
||||
@@ -256,17 +254,13 @@ int sceUmdDeactivate(u32 mode, const char *name)
|
||||
|
||||
u32 sceUmdRegisterUMDCallBack(u32 cbId)
|
||||
{
|
||||
int retVal;
|
||||
int retVal = 0;
|
||||
|
||||
// TODO: If the callback is invalid, return PSP_ERROR_UMD_INVALID_PARAM.
|
||||
if (cbId == 0)
|
||||
if (!kernelObjects.IsValid(cbId)) {
|
||||
retVal = PSP_ERROR_UMD_INVALID_PARAM;
|
||||
else {
|
||||
// Remove the old one, we're replacing.
|
||||
if (driveCBId != -1)
|
||||
__KernelUnregisterCallback(THREAD_CALLBACK_UMD, driveCBId);
|
||||
|
||||
retVal = __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId);
|
||||
} else {
|
||||
// There's only ever one.
|
||||
driveCBId = cbId;
|
||||
}
|
||||
|
||||
@@ -283,7 +277,6 @@ int sceUmdUnRegisterUMDCallBack(int cbId)
|
||||
else {
|
||||
retVal = cbId;
|
||||
driveCBId = -1;
|
||||
__KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId);
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEIO, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId);
|
||||
@@ -308,10 +301,7 @@ void __UmdStatTimeout(u64 userdata, int cyclesLate)
|
||||
if (waitID == 1)
|
||||
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
|
||||
|
||||
for (size_t i = 0; i < umdWaitingThreads.size(); ++i) {
|
||||
if (umdWaitingThreads[i] == threadID)
|
||||
umdWaitingThreads.erase(umdWaitingThreads.begin() + i--);
|
||||
}
|
||||
HLEKernel::RemoveWaitingThread(umdWaitingThreads, threadID);
|
||||
}
|
||||
|
||||
void __UmdWaitStat(u32 timeout)
|
||||
|
||||
Reference in new issue
Block a user