From 2c40cd509af76a6201796dc1286c0dc02e1ba2bc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Mar 2014 13:45:12 -0800 Subject: [PATCH 1/4] Avoid overwriting io thread results. Just block until it's done so that things are synchronous. --- Core/HLE/sceIo.cpp | 23 +++++++++++++++++++++-- Core/HW/AsyncIOManager.cpp | 10 ++++++++++ Core/HW/AsyncIOManager.h | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 1aadd248e8..9492b72135 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -742,7 +742,17 @@ bool __IoRead(int &result, int id, u32 data_addr, int size) { if (f->npdrm) { result = npdrmRead(f, data, size); return true; - } else if (__KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE) { + } + + bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; + if (useThread) { + // If there's a pending operation on this file, wait for it to finish and don't overwrite it. + useThread = !ioManager.HasOperation(f->handle); + if (!useThread) { + ioManager.SyncThread(); + } + } + if (useThread) { AsyncIOEvent ev = IO_EVENT_READ; ev.handle = f->handle; ev.buf = data; @@ -854,7 +864,16 @@ bool __IoWrite(int &result, int id, u32 data_addr, int size) { result = ERROR_KERNEL_BAD_FILE_DESCRIPTOR; return true; } - if (__KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE) { + + bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; + if (useThread) { + // If there's a pending operation on this file, wait for it to finish and don't overwrite it. + useThread = !ioManager.HasOperation(f->handle); + if (!useThread) { + ioManager.SyncThread(); + } + } + if (useThread) { AsyncIOEvent ev = IO_EVENT_WRITE; ev.handle = f->handle; ev.buf = (u8 *) data_ptr; diff --git a/Core/HW/AsyncIOManager.cpp b/Core/HW/AsyncIOManager.cpp index 0bf29f1134..3ff26be160 100644 --- a/Core/HW/AsyncIOManager.cpp +++ b/Core/HW/AsyncIOManager.cpp @@ -21,6 +21,16 @@ #include "Core/HW/AsyncIOManager.h" #include "Core/FileSystems/MetaFileSystem.h" +bool AsyncIOManager::HasOperation(u32 handle) { + if (resultsPending_.find(handle) != resultsPending_.end()) { + return true; + } + if (results_.find(handle) != results_.end()) { + return true; + } + return false; +} + void AsyncIOManager::ScheduleOperation(AsyncIOEvent ev) { lock_guard guard(resultsLock_); if (!resultsPending_.insert(ev.handle).second) { diff --git a/Core/HW/AsyncIOManager.h b/Core/HW/AsyncIOManager.h index d2aacfa316..8fb96a16ee 100644 --- a/Core/HW/AsyncIOManager.h +++ b/Core/HW/AsyncIOManager.h @@ -51,6 +51,7 @@ class AsyncIOManager : public IOThreadEventQueue { public: void DoState(PointerWrap &p); + bool HasOperation(u32 handle); void ScheduleOperation(AsyncIOEvent ev); void Shutdown(); From 07a2e579322565aad2c84fe7aadafab855380222 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Mar 2014 13:47:11 -0800 Subject: [PATCH 2/4] Synchronize IO operations before any seek. To prevent it from seeking before the operation. --- Core/HLE/sceIo.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 9492b72135..7bc429d52c 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -1024,6 +1024,11 @@ u32 npdrmLseek(FileNode *f, s32 where, FileMove whence) s64 __IoLseekDest(FileNode *f, s64 offset, int whence, FileMove &seek) { seek = FILEMOVE_BEGIN; + // Let's make sure this isn't incorrect mid-operation. + if (ioManager.HasOperation(f->handle)) { + ioManager.SyncThread(); + } + s64 newPos = 0; switch (whence) { case 0: From 2a4cbb71713567654e9096fde0736562d007c8ac Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Mar 2014 13:48:29 -0800 Subject: [PATCH 3/4] Allow two threads to read from a file at once. It just happens in order, rather than failing with an error (async busy.) Async operations still fail when used in this way, however. --- Core/HLE/sceIo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 7bc429d52c..da3ef85e7a 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -638,7 +638,7 @@ void __IoSchedSync(FileNode *f, int fd, int usec) { u64 param = ((u64)__KernelGetCurThread()) << 32 | fd; CoreTiming::ScheduleEvent(usToCycles(usec), syncNotifyEvent, param); - f->pendingAsyncResult = true; + f->pendingAsyncResult = false; f->hasAsyncResult = false; } From d7ba8f7312875cfcff725dc658bbd4732a4b6166 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Mar 2014 13:59:34 -0800 Subject: [PATCH 4/4] Correct error code for reads into a bad pointer. Per tests this is generally -1. --- Core/HLE/sceIo.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index da3ef85e7a..40feefd0b4 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -764,10 +764,13 @@ bool __IoRead(int &result, int id, u32 data_addr, int size) { return true; } } else { - ERROR_LOG_REPORT(SCEIO, "sceIoRead Reading into bad pointer %08x", data_addr); - // TODO: Returning 0 because it wasn't being sign-extended in async result before. - // What should this do? - result = 0; + if (size != 0) { + // TODO: For some combinations of bad pointer + size, SCE_KERNEL_ERROR_ILLEGAL_ADDR. + // Seems like only for kernel RAM. For most cases, it really is -1. + result = -1; + } else { + result = 0; + } return true; } } else {