Io: Update async priority more correctly.

When an operation finishes, whether it uses the priority from the first
operation or the current thread's priority depends on sdk version, it
seems.

This also makes it resolve the default priority on open, so that changing
the default afterward doesn't affect already open descriptors.
This commit is contained in:
Unknown W. Brackets 2020-01-03 13:09:58 -08:00
parent 0a5ec48382
commit 593e48b865
4 changed files with 42 additions and 18 deletions

View File

@ -16,9 +16,11 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/ChunkFile.h"
#include "Core/CoreTiming.h"
#include "Core/MemMapHelpers.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLEHelperThread.h"
#include "Core/HLE/KernelWaitHelpers.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/MIPS/MIPSCodeUtils.h"
@ -91,6 +93,13 @@ void HLEHelperThread::ChangePriority(u32 prio) {
KernelChangeThreadPriority(id_, prio);
}
void HLEHelperThread::Resume(WaitType waitType, SceUID uid, int result) {
bool res = HLEKernel::ResumeFromWait(id_, waitType, uid, result);
if (!res) {
ERROR_LOG(HLE, "Failed to wake helper thread from wait");
}
}
void HLEHelperThread::Forget() {
id_ = 0;
entry_ = 0;

View File

@ -19,6 +19,7 @@
#include "Core/HLE/sceKernel.h"
class PointerWrap;
enum WaitType : int;
class HLEHelperThread {
public:
@ -33,10 +34,15 @@ public:
void Terminate();
bool Stopped();
void ChangePriority(u32 prio);
void Resume(WaitType waitType, SceUID uid, int result);
// For savestates.
void Forget();
u32 Entry() {
return entry_;
}
private:
void AllocEntry(u32 size);
void Create(const char *threadName, u32 prio, int stacksize);

View File

@ -295,8 +295,11 @@ public:
u64 __IoCompleteAsyncIO(FileNode *f);
static void IoAsyncCleanupThread(int fd, bool force = false) {
if (asyncThreads[fd] && (asyncThreads[fd]->Stopped() || force)) {
static void IoAsyncCleanupThread(int fd) {
if (asyncThreads[fd]) {
if (!asyncThreads[fd]->Stopped()) {
asyncThreads[fd]->Terminate();
}
delete asyncThreads[fd];
asyncThreads[fd] = nullptr;
}
@ -438,8 +441,6 @@ static void __IoAsyncNotify(u64 userdata, int cyclesLate) {
if (f->closePending) {
__IoFreeFd(fd, error);
}
IoAsyncCleanupThread(fd);
}
}
@ -488,8 +489,6 @@ static void __IoSyncNotify(u64 userdata, int cyclesLate) {
HLEKernel::ResumeFromWait(threadID, WAITTYPE_IO, fd, result);
f->waitingSyncThreads.erase(std::remove(f->waitingSyncThreads.begin(), f->waitingSyncThreads.end(), threadID), f->waitingSyncThreads.end());
IoAsyncCleanupThread(fd);
}
static void __IoAsyncBeginCallback(SceUID threadID, SceUID prevCallbackId) {
@ -778,12 +777,20 @@ u32 __IoGetFileHandleFromId(u32 id, u32 &outError)
}
static void IoStartAsyncThread(int id, FileNode *f) {
IoAsyncCleanupThread(id, true);
int priority = asyncParams[id].priority == -1 ? asyncDefaultPriority : asyncParams[id].priority;
if (priority == -1)
priority = KernelCurThreadPriority();
asyncThreads[id] = new HLEHelperThread("SceIoAsync", "IoFileMgrForUser", "__IoAsyncFinish", priority, 0x200);
asyncThreads[id]->Start(id, 0);
if (asyncThreads[id] && !asyncThreads[id]->Stopped()) {
// Wake the thread up.
if (asyncParams[id].priority == -1 && sceKernelGetCompiledSdkVersion() >= 0x04020000) {
asyncThreads[id]->ChangePriority(KernelCurThreadPriority());
}
asyncThreads[id]->Resume(WAITTYPE_ASYNCIO, id, 0);
} else {
IoAsyncCleanupThread(id);
int priority = asyncParams[id].priority;
if (priority == -1)
priority = KernelCurThreadPriority();
asyncThreads[id] = new HLEHelperThread("SceIoAsync", "IoFileMgrForUser", "__IoAsyncFinish", priority, 0x200);
asyncThreads[id]->Start(id, 0);
}
f->pendingAsyncResult = true;
}
@ -1491,7 +1498,7 @@ static u32 sceIoOpen(const char *filename, int flags, int mode) {
return id;
} else {
DEBUG_LOG(SCEIO, "%i=sceIoOpen(%s, %08x, %08x)", id, filename, flags, mode);
asyncParams[id].priority = -1;
asyncParams[id].priority = asyncDefaultPriority;
// Timing is not accurate, aiming low for now.
return hleDelayResult(id, "file opened", 100);
}
@ -1984,6 +1991,9 @@ static int sceIoChangeAsyncPriority(int id, int priority) {
}
if (asyncThreads[id] && !asyncThreads[id]->Stopped()) {
if (priority == -1) {
priority = KernelCurThreadPriority();
}
asyncThreads[id]->ChangePriority(priority);
}
@ -2101,7 +2111,6 @@ static u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) {
DEBUG_LOG(SCEIO, "%lli = sceIoGetAsyncStat(%i, %i, %08x)", f->asyncResult, id, poll, address);
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
IoAsyncCleanupThread(id);
if (f->closePending) {
__IoFreeFd(id, error);
@ -2139,7 +2148,6 @@ static int sceIoWaitAsync(int id, u32 address) {
}
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
IoAsyncCleanupThread(id);
if (f->closePending) {
__IoFreeFd(id, error);
@ -2173,7 +2181,6 @@ static int sceIoWaitAsyncCB(int id, u32 address) {
} else if (f->hasAsyncResult) {
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
IoAsyncCleanupThread(id);
if (f->closePending) {
__IoFreeFd(id, error);
@ -2197,7 +2204,6 @@ static u32 sceIoPollAsync(int id, u32 address) {
} else if (f->hasAsyncResult) {
Memory::Write_U64((u64) f->asyncResult, address);
f->hasAsyncResult = false;
IoAsyncCleanupThread(id);
if (f->closePending) {
__IoFreeFd(id, error);
@ -2671,6 +2677,8 @@ static int IoAsyncFinish(int id) {
if (f) {
// Reset this so the Io funcs don't reject the request.
f->pendingAsyncResult = false;
// Reset the PC back so we will run again on resume.
currentMIPS->pc = asyncThreads[id]->Entry();
auto &params = asyncParams[id];
@ -2732,6 +2740,7 @@ static int IoAsyncFinish(int id) {
__IoSchedAsync(f, id, us);
__KernelWaitCurThread(WAITTYPE_ASYNCIO, id, 0, 0, false, "async io");
hleSkipDeadbeef();
params.op = IoAsyncOp::NONE;
return 0;

View File

@ -80,7 +80,7 @@ struct SceKernelSysClock {
// TODO: Map these to PSP wait types. Most of these are wrong.
// remember to update the waitTypeNames array in sceKernelThread.cpp when changing these
enum WaitType
enum WaitType : int
{
WAITTYPE_NONE = 0,
WAITTYPE_SLEEP = 1,