mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-19 13:42:00 +00:00
Decentralize callback registration.
Callbacks are always tied to THEIR thread, and the registration was all based on the current thread which is just not the right way.
This commit is contained in:
parent
94e88943d8
commit
64b75ed3ff
@ -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;
|
||||
}
|
||||
|
||||
|
@ -498,19 +498,6 @@ 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);
|
||||
|
||||
p.Do(pendingMipsCalls);
|
||||
@ -531,7 +518,6 @@ public:
|
||||
|
||||
ThreadContext context;
|
||||
|
||||
std::set<SceUID> registeredCallbacks[THREAD_CALLBACK_NUM_TYPES];
|
||||
std::list<SceUID> readyCallbacks;
|
||||
|
||||
std::list<u32> pendingMipsCalls;
|
||||
@ -2845,8 +2831,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);
|
||||
@ -3541,30 +3526,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;
|
||||
|
||||
@ -3586,26 +3548,6 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notify
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc)
|
||||
{
|
||||
waitTypeFuncs[type].beginFunc = beginFunc;
|
||||
|
@ -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;
|
||||
|
@ -114,7 +114,7 @@ void __UmdStatChange(u64 userdata, int cyclesLate)
|
||||
void __KernelUmdActivate()
|
||||
{
|
||||
u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE;
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
|
||||
__KernelNotifyCallback(driveCBId, notifyArg);
|
||||
|
||||
// Don't activate immediately, take time to "spin up."
|
||||
CoreTiming::RemoveAllEvents(umdStatChangeEvent);
|
||||
@ -124,7 +124,7 @@ void __KernelUmdActivate()
|
||||
void __KernelUmdDeactivate()
|
||||
{
|
||||
u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READY;
|
||||
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
|
||||
__KernelNotifyCallback(driveCBId, notifyArg);
|
||||
|
||||
CoreTiming::RemoveAllEvents(umdStatChangeEvent);
|
||||
__UmdStatChange(0, 0);
|
||||
@ -259,14 +259,10 @@ u32 sceUmdRegisterUMDCallBack(u32 cbId)
|
||||
int retVal;
|
||||
|
||||
// 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 +279,6 @@ int sceUmdUnRegisterUMDCallBack(int cbId)
|
||||
else {
|
||||
retVal = cbId;
|
||||
driveCBId = -1;
|
||||
__KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId);
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEIO, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user