From 217eaa9cb406e31401f4ff62bea5608ffabd661d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 15:15:59 -0700 Subject: [PATCH 01/26] Remove bad param from sceKernelPollEventFlag(). Not that it was necessarily hurting anything... --- Core/HLE/sceKernel.cpp | 2 +- Core/HLE/sceKernelEventFlag.cpp | 4 ++-- Core/HLE/sceKernelEventFlag.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 30ba9e00ab..9dd6a5451b 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -642,7 +642,7 @@ const HLEFunction ThreadManForUser[] = {0x1fb15a32,&WrapU_IU, "sceKernelSetEventFlag"}, {0x402FCF22,&WrapI_IUUUU, "sceKernelWaitEventFlag"}, {0x328C546A,&WrapI_IUUUU, "sceKernelWaitEventFlagCB"}, - {0x30FD48F0,&WrapI_IUUUU, "sceKernelPollEventFlag"}, + {0x30FD48F0,&WrapI_IUUU, "sceKernelPollEventFlag"}, {0xCD203292,&WrapU_IUU, "sceKernelCancelEventFlag"}, {0xA66B0120,&WrapU_IU, "sceKernelReferEventFlagStatus"}, diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index f5c5ddbc3c..5d8e3786e7 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -607,9 +607,9 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 } } -int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr) +int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr) { - DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr); if ((wait & ~PSP_EVENT_WAITKNOWN) != 0) { diff --git a/Core/HLE/sceKernelEventFlag.h b/Core/HLE/sceKernelEventFlag.h index 151efa25f7..776f8dc0c5 100644 --- a/Core/HLE/sceKernelEventFlag.h +++ b/Core/HLE/sceKernelEventFlag.h @@ -23,7 +23,7 @@ u32 sceKernelDeleteEventFlag(SceUID uid); u32 sceKernelSetEventFlag(SceUID id, u32 bitsToSet); int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr); int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr); -int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr); +int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr); u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr); u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr); From 1ee99f88e166b77bbac6f343bf3b048622f937ac Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 17:17:36 -0700 Subject: [PATCH 02/26] Stop warning on invalid sempahores. They've been helpful, but it's finally been a while since it's mattered. --- Core/HLE/sceKernelEventFlag.cpp | 74 +++++++++++++++++++++++++-------- Core/HLE/sceKernelSemaphore.cpp | 72 ++++++++++++++++++++------------ 2 files changed, 101 insertions(+), 45 deletions(-) diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 5d8e3786e7..fc36df8f95 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -17,15 +17,15 @@ //http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/kernel/managers/EventFlagManager.java?r=1263 -#include "HLE.h" -#include "../MIPS/MIPS.h" +#include "Core/HLE/HLE.h" +#include "Core/MIPS/MIPS.h" #include "Core/CoreTiming.h" #include "Core/Reporting.h" -#include "ChunkFile.h" +#include "Common/ChunkFile.h" -#include "sceKernel.h" -#include "sceKernelThread.h" -#include "sceKernelEventFlag.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelEventFlag.h" void __KernelEventFlagTimeout(u64 userdata, int cycleslate); @@ -333,12 +333,12 @@ int sceKernelCreateEventFlag(const char *name, u32 flag_attr, u32 flag_initPatte u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) { - DEBUG_LOG(HLE, "sceKernelCancelEventFlag(%i, %08X, %08X)", uid, pattern, numWaitThreadsPtr); - u32 error; EventFlag *e = kernelObjects.Get(uid, error); if (e) { + DEBUG_LOG(HLE, "sceKernelCancelEventFlag(%i, %08x, %08x)", uid, pattern, numWaitThreadsPtr); + e->nef.numWaitThreads = (int) e->waitingThreads.size(); if (Memory::IsValidAddress(numWaitThreadsPtr)) Memory::Write_U32(e->nef.numWaitThreads, numWaitThreadsPtr); @@ -351,7 +351,10 @@ u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) return 0; } else + { + DEBUG_LOG(HLE, "sceKernelCancelEventFlag(%i, %08x, %08x): invalid event flag", uid, pattern, numWaitThreadsPtr); return error; + } } u32 sceKernelClearEventFlag(SceUID id, u32 bits) @@ -367,19 +370,18 @@ u32 sceKernelClearEventFlag(SceUID id, u32 bits) } else { - ERROR_LOG(HLE,"sceKernelClearEventFlag(%i, %08x) - error", id, bits); + ERROR_LOG(HLE, "sceKernelClearEventFlag(%i, %08x): invalid event flag", id, bits); return error; } } u32 sceKernelDeleteEventFlag(SceUID uid) { - DEBUG_LOG(HLE, "sceKernelDeleteEventFlag(%i)", uid); - u32 error; EventFlag *e = kernelObjects.Get(uid, error); if (e) { + DEBUG_LOG(HLE, "sceKernelDeleteEventFlag(%i)", uid); bool wokeThreads = __KernelClearEventFlagThreads(e, SCE_KERNEL_ERROR_WAIT_DELETE); if (wokeThreads) hleReSchedule("event flag deleted"); @@ -387,16 +389,19 @@ u32 sceKernelDeleteEventFlag(SceUID uid) return kernelObjects.Destroy(uid); } else + { + DEBUG_LOG(HLE, "sceKernelDeleteEventFlag(%i): invalid event flag", uid); return error; + } } u32 sceKernelSetEventFlag(SceUID id, u32 bitsToSet) { u32 error; - DEBUG_LOG(HLE, "sceKernelSetEventFlag(%i, %08x)", id, bitsToSet); EventFlag *e = kernelObjects.Get(id, error); if (e) { + DEBUG_LOG(HLE, "sceKernelSetEventFlag(%i, %08x)", id, bitsToSet); bool wokeThreads = false; e->nef.currentPattern |= bitsToSet; @@ -419,6 +424,7 @@ u32 sceKernelSetEventFlag(SceUID id, u32 bitsToSet) } else { + DEBUG_LOG(HLE, "sceKernelSetEventFlag(%i, %08x): invalid event flag", id, bitsToSet); return error; } } @@ -486,8 +492,6 @@ void __KernelEventFlagRemoveThread(EventFlag *e, SceUID threadID) int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr) { - DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); - if ((wait & ~PSP_EVENT_WAITKNOWN) != 0) { WARN_LOG_REPORT(HLE, "sceKernelWaitEventFlag(%i) invalid mode parameter: %08x", id, wait); @@ -495,10 +499,16 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti } // Can't wait on 0, that's guaranteed to wait forever. if (bits == 0) + { + DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x): bad pattern", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_EVF_ILPAT; + } if (!__KernelIsDispatchEnabled()) + { + DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x): dispatch disabled", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_CAN_NOT_WAIT; + } u32 error; EventFlag *e = kernelObjects.Get(id, error); @@ -517,7 +527,12 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti // Do we allow more than one thread to wait? if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0) + { + DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_EVF_MULTI; + } + + DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x): waiting", id, bits, wait, outBitsPtr, timeoutPtr); // No match - must wait. th.tid = __KernelGetCurThread(); @@ -530,19 +545,20 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti __KernelSetEventFlagTimeout(e, timeoutPtr); __KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr, false, "event flag waited"); } + else + DEBUG_LOG(HLE, "0=sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); return 0; } else { + DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x): invalid event flag", id, bits, wait, outBitsPtr, timeoutPtr); return error; } } int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr) { - DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); - if ((wait & ~PSP_EVENT_WAITKNOWN) != 0) { WARN_LOG_REPORT(HLE, "sceKernelWaitEventFlagCB(%i) invalid mode parameter: %08x", id, wait); @@ -550,10 +566,16 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 } // Can't wait on 0, that's guaranteed to wait forever. if (bits == 0) + { + DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): bad pattern", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_EVF_ILPAT; + } if (!__KernelIsDispatchEnabled()) + { + DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): dispatch disabled", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_CAN_NOT_WAIT; + } u32 error; EventFlag *e = kernelObjects.Get(id, error); @@ -580,7 +602,12 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 // Do we allow more than one thread to wait? if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0) + { + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); return SCE_KERNEL_ERROR_EVF_MULTI; + } + + DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): waiting", id, bits, wait, outBitsPtr, timeoutPtr); // No match - must wait. th.tid = __KernelGetCurThread(); @@ -597,20 +624,22 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 __KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr, true, "event flag waited"); } else + { + DEBUG_LOG(HLE, "0=sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr); hleCheckCurrentCallbacks(); + } return 0; } else { + DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x): invalid event flag", id, bits, wait, outBitsPtr, timeoutPtr); return error; } } int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr) { - DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr); - if ((wait & ~PSP_EVENT_WAITKNOWN) != 0) { WARN_LOG_REPORT(HLE, "sceKernelPollEventFlag(%i) invalid mode parameter: %08x", id, wait); @@ -624,7 +653,10 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr) } // Can't wait on 0, it never matches. if (bits == 0) + { + DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x): bad pattern", id, bits, wait, outBitsPtr); return SCE_KERNEL_ERROR_EVF_ILPAT; + } u32 error; EventFlag *e = kernelObjects.Get(id, error); @@ -636,18 +668,24 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr) Memory::Write_U32(e->nef.currentPattern, outBitsPtr); if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0) + { + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_MULTI=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr); return SCE_KERNEL_ERROR_EVF_MULTI; + } // No match - return that, this is polling, not waiting. + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_EVF_COND=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr); return SCE_KERNEL_ERROR_EVF_COND; } else { + DEBUG_LOG(HLE, "0=sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr); return 0; } } else { + DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x): invalid event flag", id, bits, wait, outBitsPtr); return error; } } diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 0fdaa1d078..a107e4fc42 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -16,14 +16,14 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include -#include "HLE.h" -#include "../MIPS/MIPS.h" +#include "Core/HLE/HLE.h" +#include "Core/MIPS/MIPS.h" #include "Core/CoreTiming.h" #include "Core/Reporting.h" -#include "ChunkFile.h" -#include "sceKernel.h" -#include "sceKernelThread.h" -#include "sceKernelSemaphore.h" +#include "Common/ChunkFile.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelSemaphore.h" #define PSP_SEMA_ATTR_FIFO 0 #define PSP_SEMA_ATTR_PRIORITY 0x100 @@ -232,14 +232,17 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason) int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) { - DEBUG_LOG(HLE, "sceKernelCancelSema(%i, %i, %08x)", id, newCount, numWaitThreadsPtr); - u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { if (newCount > s->ns.maxCount) + { + DEBUG_LOG(HLE, "sceKernelCancelSema(%i, %i, %08x): invalid count", id, newCount, numWaitThreadsPtr); return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + } + + DEBUG_LOG(HLE, "sceKernelCancelSema(%i, %i, %08x)", id, newCount, numWaitThreadsPtr); s->ns.numWaitThreads = (int) s->waitingThreads.size(); if (Memory::IsValidAddress(numWaitThreadsPtr)) @@ -257,7 +260,7 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) } else { - ERROR_LOG(HLE, "sceKernelCancelSema : Trying to cancel invalid semaphore %i", id); + DEBUG_LOG(HLE, "sceKernelCancelSema(%i, %i, %08x): invalid semaphore", id, newCount, numWaitThreadsPtr); return error; } } @@ -303,12 +306,12 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 int sceKernelDeleteSema(SceUID id) { - DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); - u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { + DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); + bool wokeThreads = __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE); if (wokeThreads) hleReSchedule("semaphore deleted"); @@ -317,7 +320,7 @@ int sceKernelDeleteSema(SceUID id) } else { - ERROR_LOG(HLE, "sceKernelDeleteSema : Trying to delete invalid semaphore %i", id); + DEBUG_LOG(HLE, "sceKernelDeleteSema(%i): invalid semaphore", id); return error; } } @@ -360,11 +363,14 @@ int sceKernelSignalSema(SceUID id, int signal) if (s) { if (s->ns.currentCount + signal - (int) s->waitingThreads.size() > s->ns.maxCount) + { + DEBUG_LOG(HLE, "sceKernelSignalSema(%i, %i): overflow (at %i)", id, signal, s->ns.currentCount); return SCE_KERNEL_ERROR_SEMA_OVF; + } int oldval = s->ns.currentCount; s->ns.currentCount += signal; - DEBUG_LOG(HLE, "sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount); + DEBUG_LOG(HLE, "sceKernelSignalSema(%i, %i) (count: %i -> %i)", id, signal, oldval, s->ns.currentCount); if ((s->ns.attr & PSP_SEMA_ATTR_PRIORITY) != 0) std::stable_sort(s->waitingThreads.begin(), s->waitingThreads.end(), __KernelThreadSortPriority); @@ -387,7 +393,7 @@ retry: } else { - WARN_LOG(HLE, "sceKernelSignalSema : Trying to signal invalid semaphore %i", id); + DEBUG_LOG(HLE, "sceKernelSignalSema(%i, %i): invalid semaphore", id, signal); return error; } } @@ -430,7 +436,7 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread()); } -int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) +int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCallbacks) { u32 error; Semaphore *s = kernelObjects.Get(id, error); @@ -465,33 +471,41 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *bad return 0; } else - { - WARN_LOG(HLE, badSemaMessage, id); return error; - } } int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) { - DEBUG_LOG(HLE, "sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr); - - return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false); + int result = __KernelWaitSema(id, wantedCount, timeoutPtr, false); + if (result == SCE_KERNEL_ERROR_ILLEGAL_COUNT) + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr) + else if (result == 0) + DEBUG_LOG(HLE, "0=sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr) + else + DEBUG_LOG(HLE, "%08x=sceKernelWaitSema(%i, %i, %i)", result, id, wantedCount, timeoutPtr); + return result; } int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) { - DEBUG_LOG(HLE, "sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr); - - return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true); + int result = __KernelWaitSema(id, wantedCount, timeoutPtr, true); + if (result == SCE_KERNEL_ERROR_ILLEGAL_COUNT) + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr) + else if (result == 0) + DEBUG_LOG(HLE, "0=sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr) + else + DEBUG_LOG(HLE, "%08x=sceKernelWaitSemaCB(%i, %i, %i)", result, id, wantedCount, timeoutPtr); + return result; } // Should be same as WaitSema but without the wait, instead returning SCE_KERNEL_ERROR_SEMA_ZERO int sceKernelPollSema(SceUID id, int wantedCount) { - DEBUG_LOG(HLE, "sceKernelPollSema(%i, %i)", id, wantedCount); - if (wantedCount <= 0) + { + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_ILLEGAL_COUNT=sceKernelPollSema(%i, %i)", id, wantedCount); return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + } u32 error; Semaphore *s = kernelObjects.Get(id, error); @@ -499,15 +513,19 @@ int sceKernelPollSema(SceUID id, int wantedCount) { if (s->ns.currentCount >= wantedCount && s->waitingThreads.size() == 0) { + DEBUG_LOG(HLE, "0=sceKernelPollSema(%i, %i)", id, wantedCount); s->ns.currentCount -= wantedCount; return 0; } else + { + DEBUG_LOG(HLE, "SCE_KERNEL_ERROR_SEMA_ZERO=sceKernelPollSema(%i, %i)", id, wantedCount); return SCE_KERNEL_ERROR_SEMA_ZERO; + } } else { - ERROR_LOG(HLE, "sceKernelPollSema: Trying to poll invalid semaphore %i", id); + DEBUG_LOG(HLE, "sceKernelPollSema(%i, %i): invalid semaphore", id, wantedCount); return error; } } From 25c07aa945609f756bc61ebe6eb4a77e90969b2b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 17:20:00 -0700 Subject: [PATCH 03/26] Don't warn for umd0: and ms0:, not problems. --- Core/FileSystems/MetaFileSystem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 9b2076f4cd..24e3f12add 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -81,8 +81,7 @@ static bool RealPath(const std::string ¤tDirectory, const std::string &inP size_t inColon = inPath.find(':'); if (inColon + 1 == inLen) { - WARN_LOG(HLE, "RealPath: inPath is all prefix and no path: \"%s\"", inPath.c_str()); - + // There's nothing after the colon, e.g. umd0: - this is perfectly valid. outPath = inPath; return true; } From 666cee4f6aca8c98729706ca02fca8c0e9db524d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 20:16:52 -0700 Subject: [PATCH 04/26] Fix sceKernelCreateMsgPipe() and alloc psp memory. Might not matter, but I'm not sure yet if it's expoesd somewhere. --- Core/HLE/sceKernel.cpp | 18 +++--- Core/HLE/sceKernelMsgPipe.cpp | 109 ++++++++++++++++++++-------------- Core/HLE/sceKernelMsgPipe.h | 2 +- 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 9dd6a5451b..33f163140d 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -746,16 +746,16 @@ const HLEFunction ThreadManForUser[] = {0x2A3D44FF,WrapI_I, "sceKernelGetCallbackCount"}, {0x730ED8BC,WrapI_IU, "sceKernelReferCallbackStatus"}, - {0x8125221D,&WrapI_CUU,"sceKernelCreateMbx"}, - {0x86255ADA,&WrapI_I,"sceKernelDeleteMbx"}, - {0xE9B3061E,&WrapI_IU,"sceKernelSendMbx"}, - {0x18260574,&WrapI_IUU,"sceKernelReceiveMbx"}, - {0xF3986382,&WrapI_IUU,"sceKernelReceiveMbxCB"}, - {0x0D81716A,&WrapI_IU,"sceKernelPollMbx"}, - {0x87D4DD36,&WrapI_IU,"sceKernelCancelReceiveMbx"}, - {0xA8E8C846,&WrapI_IU,"sceKernelReferMbxStatus"}, + {0x8125221D,WrapI_CUU, "sceKernelCreateMbx"}, + {0x86255ADA,WrapI_I, "sceKernelDeleteMbx"}, + {0xE9B3061E,WrapI_IU, "sceKernelSendMbx"}, + {0x18260574,WrapI_IUU, "sceKernelReceiveMbx"}, + {0xF3986382,WrapI_IUU, "sceKernelReceiveMbxCB"}, + {0x0D81716A,WrapI_IU, "sceKernelPollMbx"}, + {0x87D4DD36,WrapI_IU, "sceKernelCancelReceiveMbx"}, + {0xA8E8C846,WrapI_IU, "sceKernelReferMbxStatus"}, - {0x7C0DC2A0,sceKernelCreateMsgPipe,"sceKernelCreateMsgPipe"}, + {0x7C0DC2A0,WrapI_CIUUU, "sceKernelCreateMsgPipe"}, {0xF0B7DA1C,sceKernelDeleteMsgPipe,"sceKernelDeleteMsgPipe"}, {0x876DBFAD,sceKernelSendMsgPipe,"sceKernelSendMsgPipe"}, {0x7C41F2C2,sceKernelSendMsgPipeCB,"sceKernelSendMsgPipeCB"}, diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 8d2f5981fc..f0577aabf1 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -15,16 +15,21 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "HLE.h" -#include "sceKernel.h" -#include "sceKernelMsgPipe.h" -#include "sceKernelThread.h" -#include "ChunkFile.h" +#include "Core/Reporting.h" +#include "Core/CoreTiming.h" +#include "Core/HLE/HLE.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelMsgPipe.h" +#include "Core/HLE/sceKernelMemory.h" +#include "Core/HLE/sceKernelThread.h" +#include "Common/ChunkFile.h" #define SCE_KERNEL_MPA_THFIFO_S 0x0000 #define SCE_KERNEL_MPA_THPRI_S 0x0100 #define SCE_KERNEL_MPA_THFIFO_R 0x0000 #define SCE_KERNEL_MPA_THPRI_R 0x1000 +#define SCE_KERNEL_MPA_HIGHMEM 0x4000 +#define SCE_KERNEL_MPA_KNOWN (SCE_KERNEL_MPA_THPRI_S | SCE_KERNEL_MPA_THPRI_R | SCE_KERNEL_MPA_HIGHMEM) #define SCE_KERNEL_MPW_FULL 0 #define SCE_KERNEL_MPW_ASAP 1 @@ -58,11 +63,11 @@ struct MsgPipe : public KernelObject static int GetStaticIDType() { return SCE_KERNEL_TMID_Mpipe; } int GetIDType() const { return SCE_KERNEL_TMID_Mpipe; } - MsgPipe() : buffer(NULL) {} + MsgPipe() : buffer(0) {} ~MsgPipe() { - if (buffer != NULL) - delete [] buffer; + if (buffer != 0) + userMemory.Free(buffer); } void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr, bool usePrio) @@ -107,7 +112,7 @@ struct MsgPipe : public KernelObject if ((u32) nmp.freeSize >= thread->bufSize) { // Put all the data to the buffer - memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); + Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); nmp.freeSize -= thread->bufSize; __KernelResumeThreadFromWait(thread->id); @@ -117,7 +122,7 @@ struct MsgPipe : public KernelObject else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != 0) { // Put as much data as possible into the buffer - memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); + Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); Memory::Write_U32(nmp.freeSize, thread->transferredBytesAddr); nmp.freeSize = 0; __KernelResumeThreadFromWait(thread->id); @@ -135,9 +140,9 @@ struct MsgPipe : public KernelObject if ((u32) nmp.bufSize - (u32) nmp.freeSize >= thread->bufSize) { // Get the needed data from the buffer - Memory::Memcpy(thread->bufAddr, buffer, thread->bufSize); + Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), thread->bufSize); // Put the unused data at the start of the buffer - memmove(buffer, buffer + thread->bufSize, nmp.bufSize - nmp.freeSize); + memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + thread->bufSize, nmp.bufSize - nmp.freeSize); Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); nmp.freeSize += thread->bufSize; __KernelResumeThreadFromWait(thread->id); @@ -147,7 +152,7 @@ struct MsgPipe : public KernelObject else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != nmp.bufSize) { // Get all the data from the buffer - Memory::Memcpy(thread->bufAddr, buffer, nmp.bufSize - nmp.freeSize); + Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), nmp.bufSize - nmp.freeSize); Memory::Write_U32(nmp.bufSize - nmp.freeSize, thread->transferredBytesAddr); nmp.freeSize = nmp.bufSize; __KernelResumeThreadFromWait(thread->id); @@ -162,14 +167,7 @@ struct MsgPipe : public KernelObject MsgPipeWaitingThread mpwt1 = {0}, mpwt2 = {0}; p.Do(sendWaitingThreads, mpwt1); p.Do(receiveWaitingThreads, mpwt2); - bool hasBuffer = buffer != NULL; - p.Do(hasBuffer); - if (hasBuffer) - { - if (buffer == NULL) - buffer = new u8[nmp.bufSize]; - p.DoArray(buffer, nmp.bufSize); - } + p.Do(buffer); p.DoMarker("MsgPipe"); } @@ -178,7 +176,7 @@ struct MsgPipe : public KernelObject std::vector sendWaitingThreads; std::vector receiveWaitingThreads; - u8 *buffer; + u32 buffer; }; KernelObject *__KernelMsgPipeObject() @@ -186,34 +184,59 @@ KernelObject *__KernelMsgPipeObject() return new MsgPipe; } -void sceKernelCreateMsgPipe() +int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr) { - const char *name = Memory::GetCharPointer(PARAM(0)); - int memoryPartition = PARAM(1); - SceUInt attr = PARAM(2); - int size = PARAM(3); - int opt = PARAM(4); + if (!name) + { + WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMsgPipe(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY); + return SCE_KERNEL_ERROR_NO_MEMORY; + } + if (partition < 1 || partition > 9 || partition == 7) + { + WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMsgPipe(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition); + return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; + } + // We only support user right now. + if (partition != 2 && partition != 6) + { + WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMsgPipe(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition); + return SCE_KERNEL_ERROR_ILLEGAL_PERM; + } + if ((attr & ~SCE_KERNEL_MPA_KNOWN) >= 0x100) + { + WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateEventFlag(%s): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, name, attr); + return SCE_KERNEL_ERROR_ILLEGAL_ATTR; + } + + // We ignore the upalign to 256. + u32 allocSize = size; + u32 memBlockPtr = userMemory.Alloc(allocSize, (attr & SCE_KERNEL_MPA_HIGHMEM) != 0, "MsgPipe"); + if (memBlockPtr == (u32)-1) + { + ERROR_LOG(HLE, "%08x=sceKernelCreateEventFlag(%s): Failed to allocate %i bytes for buffer", SCE_KERNEL_ERROR_NO_MEMORY, name, size); + return SCE_KERNEL_ERROR_NO_MEMORY; + } MsgPipe *m = new MsgPipe(); SceUID id = kernelObjects.Create(m); m->nmp.size = sizeof(NativeMsgPipe); - strncpy(m->nmp.name, name, sizeof(m->nmp.name)); + strncpy(m->nmp.name, name, KERNELOBJECT_MAX_NAME_LENGTH); + m->nmp.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; m->nmp.attr = attr; m->nmp.bufSize = size; m->nmp.freeSize = size; m->nmp.numSendWaitThreads = 0; m->nmp.numReceiveWaitThreads = 0; - m->buffer = 0; - if (size != 0) - { - m->buffer = new u8[size]; - } + m->buffer = memBlockPtr; - DEBUG_LOG(HLE, "%d=sceKernelCreateMsgPipe(%s, part=%d, attr=%08x, size=%d, opt=%08x)", id, name, memoryPartition, attr, size, opt); + DEBUG_LOG(HLE, "%d=sceKernelCreateMsgPipe(%s, part=%d, attr=%08x, size=%d, opt=%08x)", id, name, partition, attr, size, optionsPtr); - RETURN(id); + if (optionsPtr != 0) + WARN_LOG_REPORT(HLE, "sceKernelCreateMsgPipe(%s) unsupported options parameter: %08x", name, optionsPtr); + + return id; } void sceKernelDeleteMsgPipe() @@ -302,14 +325,14 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { if (sendSize <= (u32) m->nmp.freeSize) { - memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), sendSize); + Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), sendSize); m->nmp.freeSize -= sendSize; curSendAddr = sendBufAddr + sendSize; sendSize = 0; } else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != 0) { - memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), m->nmp.freeSize); + Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), m->nmp.freeSize); curSendAddr = sendBufAddr + m->nmp.freeSize; sendSize -= m->nmp.freeSize; m->nmp.freeSize = 0; @@ -476,16 +499,16 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // Enough data in the buffer: copy just the needed amount of data if (receiveSize <= (u32) m->nmp.bufSize - (u32) m->nmp.freeSize) { - Memory::Memcpy(receiveBufAddr, m->buffer, receiveSize); + Memory::Memcpy(receiveBufAddr, Memory::GetPointer(m->buffer), receiveSize); m->nmp.freeSize += receiveSize; - memmove(m->buffer, m->buffer + receiveSize, m->nmp.bufSize - m->nmp.freeSize); + memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + receiveSize, m->nmp.bufSize - m->nmp.freeSize); curReceiveAddr = receiveBufAddr + receiveSize; receiveSize = 0; } // Else, if mode is ASAP and there's at list 1 available byte of data: copy all the available data else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != m->nmp.bufSize) { - Memory::Memcpy(receiveBufAddr, m->buffer, m->nmp.bufSize - m->nmp.freeSize); + Memory::Memcpy(receiveBufAddr, Memory::GetPointer(m->buffer), m->nmp.bufSize - m->nmp.freeSize); receiveSize -= m->nmp.bufSize - m->nmp.freeSize; curReceiveAddr = receiveBufAddr + m->nmp.bufSize - m->nmp.freeSize; m->nmp.freeSize = m->nmp.bufSize; @@ -592,10 +615,6 @@ void sceKernelCancelMsgPipe() RETURN(error); return; } - if (m->buffer != 0) - { - delete [] m->buffer; - } u32 count; for (count = 0; count < m->sendWaitingThreads.size(); count++) { diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index 46f812f4ee..b71e9642a9 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -17,7 +17,7 @@ #pragma once -void sceKernelCreateMsgPipe(); +int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr); void sceKernelDeleteMsgPipe(); void sceKernelSendMsgPipe(); void sceKernelSendMsgPipeCB(); From 6577a7f92074d24258be6ea42bf791d1c7c8c51b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 22:07:26 -0700 Subject: [PATCH 05/26] Cleanup some minor usage in msgpipes. --- Core/HLE/sceKernelMsgPipe.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index f0577aabf1..fc1159fe27 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -52,7 +52,7 @@ struct MsgPipeWaitingThread u32 bufSize; u32 freeSize; s32 waitMode; - u32 transferredBytesAddr; + PSPPointer transferredBytes; }; struct MsgPipe : public KernelObject @@ -113,7 +113,7 @@ struct MsgPipe : public KernelObject { // Put all the data to the buffer Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; nmp.freeSize -= thread->bufSize; __KernelResumeThreadFromWait(thread->id); sendWaitingThreads.erase(sendWaitingThreads.begin()); @@ -123,7 +123,7 @@ struct MsgPipe : public KernelObject { // Put as much data as possible into the buffer Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); - Memory::Write_U32(nmp.freeSize, thread->transferredBytesAddr); + *thread->transferredBytes = nmp.freeSize; nmp.freeSize = 0; __KernelResumeThreadFromWait(thread->id); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); @@ -143,7 +143,7 @@ struct MsgPipe : public KernelObject Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), thread->bufSize); // Put the unused data at the start of the buffer memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + thread->bufSize, nmp.bufSize - nmp.freeSize); - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; nmp.freeSize += thread->bufSize; __KernelResumeThreadFromWait(thread->id); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); @@ -153,7 +153,7 @@ struct MsgPipe : public KernelObject { // Get all the data from the buffer Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), nmp.bufSize - nmp.freeSize); - Memory::Write_U32(nmp.bufSize - nmp.freeSize, thread->transferredBytesAddr); + *thread->transferredBytes = nmp.bufSize - nmp.freeSize; nmp.freeSize = nmp.bufSize; __KernelResumeThreadFromWait(thread->id); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); @@ -262,7 +262,7 @@ void sceKernelDeleteMsgPipe() RETURN(kernelObjects.Destroy(uid)); } -void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool pool) +void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curSendAddr = sendBufAddr; if (m->nmp.bufSize == 0) @@ -278,7 +278,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode sendSize = 0; if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { - Memory::Write_U32(thread->bufSize - thread->freeSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize - thread->freeSize; __KernelResumeThreadFromWait(thread->id); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } @@ -287,7 +287,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode else if (thread->freeSize == sendSize) { Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), sendSize); - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; __KernelResumeThreadFromWait(thread->id); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); curSendAddr += sendSize; @@ -299,7 +299,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), thread->freeSize); sendSize -= thread->freeSize; curSendAddr += thread->freeSize; - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; __KernelResumeThreadFromWait(thread->id); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } @@ -307,7 +307,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode // If there is still data to send and (we want to send all of it or we didn't send anything) if (sendSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curSendAddr == sendBufAddr)) { - if (pool) + if (poll) { RETURN(SCE_KERNEL_ERROR_MPP_FULL); return; @@ -339,7 +339,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode } else { - if (pool) + if (poll) { RETURN(SCE_KERNEL_ERROR_MPP_FULL); return; @@ -426,7 +426,7 @@ void sceKernelTrySendMsgPipe() __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, 0, false, true); } -void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool pool) +void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curReceiveAddr = receiveBufAddr; // MsgPipe buffer size is 0, receiving directly from waiting send threads @@ -448,7 +448,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // The sending thread mode is ASAP: we have sent some data so restart it even though its buffer isn't empty if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { - Memory::Write_U32(thread->bufSize - thread->freeSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize - thread->freeSize; __KernelResumeThreadFromWait(thread->id); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } @@ -458,7 +458,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int else if (thread->bufSize - thread->freeSize == receiveSize) { Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; __KernelResumeThreadFromWait(thread->id); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); curReceiveAddr += receiveSize; @@ -471,7 +471,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), thread->bufSize - thread->freeSize); receiveSize -= thread->bufSize - thread->freeSize; curReceiveAddr += thread->bufSize - thread->freeSize; - Memory::Write_U32(thread->bufSize, thread->transferredBytesAddr); + *thread->transferredBytes = thread->bufSize; __KernelResumeThreadFromWait(thread->id); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } @@ -479,7 +479,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // All data hasn't been received and (mode isn't ASAP or nothing was received) if (receiveSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curReceiveAddr == receiveBufAddr)) { - if (pool) + if (poll) { RETURN(SCE_KERNEL_ERROR_MPP_EMPTY); return; @@ -515,7 +515,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int } else { - if (pool) + if (poll) { RETURN(SCE_KERNEL_ERROR_MPP_EMPTY); return; From 23a48ba79965f10dc52ac71175b4f5f6246df8b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Aug 2013 22:13:08 -0700 Subject: [PATCH 06/26] Return better results from msgpipe waits. Not fully tested, but it's clearer to specify. Delete and cancel are sure to have been wrong. --- Core/HLE/sceKernelMsgPipe.cpp | 44 +++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index fc1159fe27..f04c5f7a74 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -115,7 +115,7 @@ struct MsgPipe : public KernelObject Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); *thread->transferredBytes = thread->bufSize; nmp.freeSize -= thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); sendWaitingThreads.erase(sendWaitingThreads.begin()); CheckReceiveThreads(); } @@ -125,7 +125,7 @@ struct MsgPipe : public KernelObject Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); *thread->transferredBytes = nmp.freeSize; nmp.freeSize = 0; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckReceiveThreads(); } @@ -145,7 +145,7 @@ struct MsgPipe : public KernelObject memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + thread->bufSize, nmp.bufSize - nmp.freeSize); *thread->transferredBytes = thread->bufSize; nmp.freeSize += thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckSendThreads(); } @@ -155,7 +155,7 @@ struct MsgPipe : public KernelObject Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), nmp.bufSize - nmp.freeSize); *thread->transferredBytes = nmp.bufSize - nmp.freeSize; nmp.freeSize = nmp.bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckSendThreads(); } @@ -250,13 +250,17 @@ void sceKernelDeleteMsgPipe() RETURN(error); return; } - for (u32 i = 0; i < m->sendWaitingThreads.size(); i++) + for (u32 i = 0; i < (u32)m->sendWaitingThreads.size(); i++) { - __KernelResumeThreadFromWait(m->sendWaitingThreads[i].id); + auto &waitInfo = m->sendWaitingThreads[i]; + *waitInfo.transferredBytes = 0; + __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_DELETE); } - for (u32 i = 0; i < m->receiveWaitingThreads.size(); i++) + for (u32 i = 0; i < (u32)m->receiveWaitingThreads.size(); i++) { - __KernelResumeThreadFromWait(m->receiveWaitingThreads[i].id); + auto &waitInfo = m->receiveWaitingThreads[i]; + *waitInfo.transferredBytes = 0; + __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_DELETE); } DEBUG_LOG(HLE, "sceKernelDeleteMsgPipe(%i)", uid); RETURN(kernelObjects.Destroy(uid)); @@ -279,7 +283,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { *thread->transferredBytes = thread->bufSize - thread->freeSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } break; @@ -288,7 +292,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), sendSize); *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); curSendAddr += sendSize; sendSize = 0; @@ -300,7 +304,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode sendSize -= thread->freeSize; curSendAddr += thread->freeSize; *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } } @@ -449,7 +453,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { *thread->transferredBytes = thread->bufSize - thread->freeSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } break; @@ -459,7 +463,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); curReceiveAddr += receiveSize; receiveSize = 0; @@ -472,7 +476,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int receiveSize -= thread->bufSize - thread->freeSize; curReceiveAddr += thread->bufSize - thread->freeSize; *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id); + __KernelResumeThreadFromWait(thread->id, 0); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } } @@ -616,14 +620,18 @@ void sceKernelCancelMsgPipe() return; } u32 count; - for (count = 0; count < m->sendWaitingThreads.size(); count++) + for (count = 0; count < (u32)m->sendWaitingThreads.size(); count++) { - __KernelResumeThreadFromWait(m->sendWaitingThreads[count].id); + auto &waitInfo = m->sendWaitingThreads[count]; + *waitInfo.transferredBytes = 0; + __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_CANCEL); } Memory::Write_U32(count, numSendThreadsAddr); - for (count = 0; count < m->receiveWaitingThreads.size(); count++) + for (count = 0; count < (u32)m->receiveWaitingThreads.size(); count++) { - __KernelResumeThreadFromWait(m->receiveWaitingThreads[count].id); + auto &waitInfo = m->receiveWaitingThreads[count]; + *waitInfo.transferredBytes = 0; + __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_CANCEL); } Memory::Write_U32(count, numReceiveThreadsAddr); DEBUG_LOG(HLE, "sceKernelCancelMsgPipe(%i, %i, %i)", uid, numSendThreadsAddr, numReceiveThreadsAddr); From fa73875c98c0d1b63d394402ef08e0a110cc1fde Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 00:12:00 -0700 Subject: [PATCH 07/26] Clean up cancel and delete for msgpipes. --- Core/HLE/sceKernel.cpp | 4 +- Core/HLE/sceKernelMsgPipe.cpp | 87 +++++++++++++++++------------------ Core/HLE/sceKernelMsgPipe.h | 4 +- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 33f163140d..c9fc08f45b 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -756,14 +756,14 @@ const HLEFunction ThreadManForUser[] = {0xA8E8C846,WrapI_IU, "sceKernelReferMbxStatus"}, {0x7C0DC2A0,WrapI_CIUUU, "sceKernelCreateMsgPipe"}, - {0xF0B7DA1C,sceKernelDeleteMsgPipe,"sceKernelDeleteMsgPipe"}, + {0xF0B7DA1C,WrapI_I, "sceKernelDeleteMsgPipe"}, {0x876DBFAD,sceKernelSendMsgPipe,"sceKernelSendMsgPipe"}, {0x7C41F2C2,sceKernelSendMsgPipeCB,"sceKernelSendMsgPipeCB"}, {0x884C9F90,sceKernelTrySendMsgPipe,"sceKernelTrySendMsgPipe"}, {0x74829B76,sceKernelReceiveMsgPipe,"sceKernelReceiveMsgPipe"}, {0xFBFA697D,sceKernelReceiveMsgPipeCB,"sceKernelReceiveMsgPipeCB"}, {0xDF52098F,sceKernelTryReceiveMsgPipe,"sceKernelTryReceiveMsgPipe"}, - {0x349B864D,sceKernelCancelMsgPipe,"sceKernelCancelMsgPipe"}, + {0x349B864D,WrapI_IUU, "sceKernelCancelMsgPipe"}, {0x33BE4024,sceKernelReferMsgPipeStatus,"sceKernelReferMsgPipeStatus"}, {0x56C039B5,WrapI_CIUUU,"sceKernelCreateVpl"}, diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index f04c5f7a74..86e9269430 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -53,6 +53,17 @@ struct MsgPipeWaitingThread u32 freeSize; s32 waitMode; PSPPointer transferredBytes; + + void Cancel(SceUID waitID, int result) + { + u32 error; + int actualWaitID = __KernelGetWaitID(id, WAITTYPE_MSGPIPE, error); + if (actualWaitID == waitID) + { + *transferredBytes = 0; + __KernelResumeThreadFromWait(id, result); + } + } }; struct MsgPipe : public KernelObject @@ -239,31 +250,23 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, return id; } -void sceKernelDeleteMsgPipe() +int sceKernelDeleteMsgPipe(SceUID uid) { - SceUID uid = PARAM(0); u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelDeleteMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; - } - for (u32 i = 0; i < (u32)m->sendWaitingThreads.size(); i++) - { - auto &waitInfo = m->sendWaitingThreads[i]; - *waitInfo.transferredBytes = 0; - __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_DELETE); - } - for (u32 i = 0; i < (u32)m->receiveWaitingThreads.size(); i++) - { - auto &waitInfo = m->receiveWaitingThreads[i]; - *waitInfo.transferredBytes = 0; - __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_DELETE); + return error; } + + for (size_t i = 0; i < m->sendWaitingThreads.size(); i++) + m->sendWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_DELETE); + for (size_t i = 0; i < m->receiveWaitingThreads.size(); i++) + m->receiveWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_DELETE); + DEBUG_LOG(HLE, "sceKernelDeleteMsgPipe(%i)", uid); - RETURN(kernelObjects.Destroy(uid)); + return kernelObjects.Destroy(uid); } void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) @@ -320,7 +323,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, 0, 0, 0, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); return; } } @@ -352,7 +355,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, 0, 0, 0, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); return; } } @@ -492,7 +495,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, 0, 0, 0, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); return; } } @@ -528,7 +531,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, 0, 0, 0, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); return; } } @@ -605,37 +608,33 @@ void sceKernelTryReceiveMsgPipe() __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, 0, false, true); } -void sceKernelCancelMsgPipe() +int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr) { - SceUID uid = PARAM(0); - u32 numSendThreadsAddr = PARAM(1); - u32 numReceiveThreadsAddr = PARAM(2); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelCancelMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } - u32 count; - for (count = 0; count < (u32)m->sendWaitingThreads.size(); count++) - { - auto &waitInfo = m->sendWaitingThreads[count]; - *waitInfo.transferredBytes = 0; - __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_CANCEL); - } - Memory::Write_U32(count, numSendThreadsAddr); - for (count = 0; count < (u32)m->receiveWaitingThreads.size(); count++) - { - auto &waitInfo = m->receiveWaitingThreads[count]; - *waitInfo.transferredBytes = 0; - __KernelResumeThreadFromWait(waitInfo.id, SCE_KERNEL_ERROR_WAIT_CANCEL); - } - Memory::Write_U32(count, numReceiveThreadsAddr); + + if (Memory::IsValidAddress(numSendThreadsAddr)) + Memory::Write_U32((u32) m->sendWaitingThreads.size(), numSendThreadsAddr); + if (Memory::IsValidAddress(numReceiveThreadsAddr)) + Memory::Write_U32((u32) m->receiveWaitingThreads.size(), numReceiveThreadsAddr); + + for (size_t i = 0; i < m->sendWaitingThreads.size(); i++) + m->sendWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_CANCEL); + m->sendWaitingThreads.clear(); + for (size_t i = 0; i < m->receiveWaitingThreads.size(); i++) + m->receiveWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_CANCEL); + m->receiveWaitingThreads.clear(); + + // And now the entire buffer is free. + m->nmp.freeSize = m->nmp.bufSize; + DEBUG_LOG(HLE, "sceKernelCancelMsgPipe(%i, %i, %i)", uid, numSendThreadsAddr, numReceiveThreadsAddr); - RETURN(0); + return 0; } void sceKernelReferMsgPipeStatus() diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index b71e9642a9..fb873fa3c1 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -18,14 +18,14 @@ #pragma once int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr); -void sceKernelDeleteMsgPipe(); +int sceKernelDeleteMsgPipe(SceUID uid); void sceKernelSendMsgPipe(); void sceKernelSendMsgPipeCB(); void sceKernelTrySendMsgPipe(); void sceKernelReceiveMsgPipe(); void sceKernelReceiveMsgPipeCB(); void sceKernelTryReceiveMsgPipe(); -void sceKernelCancelMsgPipe(); +int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr); void sceKernelReferMsgPipeStatus(); KernelObject *__KernelMsgPipeObject(); From 88b333bd163bd2d01d9dadb06e5fed4ef7f3d9bd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 01:41:56 -0700 Subject: [PATCH 08/26] Don't even try to allocate a 0 sized buffer. --- Core/HLE/sceKernelMsgPipe.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 86e9269430..bc48d135e1 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -219,13 +219,17 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, return SCE_KERNEL_ERROR_ILLEGAL_ATTR; } - // We ignore the upalign to 256. - u32 allocSize = size; - u32 memBlockPtr = userMemory.Alloc(allocSize, (attr & SCE_KERNEL_MPA_HIGHMEM) != 0, "MsgPipe"); - if (memBlockPtr == (u32)-1) + u32 memBlockPtr = 0; + if (size != 0) { - ERROR_LOG(HLE, "%08x=sceKernelCreateEventFlag(%s): Failed to allocate %i bytes for buffer", SCE_KERNEL_ERROR_NO_MEMORY, name, size); - return SCE_KERNEL_ERROR_NO_MEMORY; + // We ignore the upalign to 256. + u32 allocSize = size; + memBlockPtr = userMemory.Alloc(allocSize, (attr & SCE_KERNEL_MPA_HIGHMEM) != 0, "MsgPipe"); + if (memBlockPtr == (u32)-1) + { + ERROR_LOG(HLE, "%08x=sceKernelCreateEventFlag(%s): Failed to allocate %i bytes for buffer", SCE_KERNEL_ERROR_NO_MEMORY, name, size); + return SCE_KERNEL_ERROR_NO_MEMORY; + } } MsgPipe *m = new MsgPipe(); From b9a71640eb4507aa8e6b68ce0c47e7da3dbbd773 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 09:35:17 -0700 Subject: [PATCH 09/26] Implement basic timeouts for msg pipes. --- Core/HLE/sceKernel.cpp | 2 + Core/HLE/sceKernelMemory.cpp | 2 +- Core/HLE/sceKernelMsgPipe.cpp | 76 +++++++++++++++++++++++++++++++++-- Core/HLE/sceKernelMsgPipe.h | 4 ++ 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index c9fc08f45b..7853dba24d 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -103,6 +103,7 @@ void __KernelInit() __KernelMbxInit(); __KernelMutexInit(); __KernelSemaInit(); + __KernelMsgPipeInit(); __IoInit(); __JpegInit(); __AudioInit(); @@ -190,6 +191,7 @@ void __KernelDoState(PointerWrap &p) __KernelEventFlagDoState(p); __KernelMbxDoState(p); __KernelModuleDoState(p); + __KernelMsgPipeDoState(p); __KernelMutexDoState(p); __KernelSemaDoState(p); __KernelTimeDoState(p); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 852855be8a..7bce80373d 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -1070,7 +1070,7 @@ void __KernelVplTimeout(u64 userdata, int cyclesLate) if (vpl) { // This thread isn't waiting anymore, but we'll remove it from waitingThreads later. - // The reason is, if it times out, but what it was waiting on is DELETED prior to it + // The reason is, if it times out, but while it was waiting on is DELETED prior to it // actually running, it will get a DELETE result instead of a TIMEOUT. // So, we need to remember it or we won't be able to mark it DELETE instead later. __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index bc48d135e1..9fc8e51a79 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -34,6 +34,9 @@ #define SCE_KERNEL_MPW_FULL 0 #define SCE_KERNEL_MPW_ASAP 1 +// State: the timer for MsgPipe timeouts. +static int waitTimer = -1; + struct NativeMsgPipe { SceSize_le size; @@ -60,6 +63,14 @@ struct MsgPipeWaitingThread int actualWaitID = __KernelGetWaitID(id, WAITTYPE_MSGPIPE, error); if (actualWaitID == waitID) { + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(id, error); + if (timeoutPtr != 0 && waitTimer != -1) + { + // Remove any event for this thread. + s64 cyclesLeft = CoreTiming::UnscheduleEvent(waitTimer, id); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + *transferredBytes = 0; __KernelResumeThreadFromWait(id, result); } @@ -195,6 +206,59 @@ KernelObject *__KernelMsgPipeObject() return new MsgPipe; } +void __KernelMsgPipeTimeout(u64 userdata, int cyclesLate) +{ + SceUID threadID = (SceUID) (userdata & 0xFFFFFFFF); + + u32 error; + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + if (timeoutPtr != 0) + Memory::Write_U32(0, timeoutPtr); + + SceUID uid = __KernelGetWaitID(threadID, WAITTYPE_MSGPIPE, error); + MsgPipe *m = kernelObjects.Get(uid, error); + if (m) + { + // This thread isn't waiting anymore, but we'll remove it from waitingThreads later. + // The reason is, if it times out, but whhile it was waiting on is DELETED prior to it + // actually running, it will get a DELETE result instead of a TIMEOUT. + // So, we need to remember it or we won't be able to mark it DELETE instead later. + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); + } +} + +void __KernelSetMsgPipeTimeout(u32 timeoutPtr) +{ + if (timeoutPtr == 0 || waitTimer == -1) + return; + + int micro = (int) Memory::Read_U32(timeoutPtr); + + // TODO: Correct. + // This happens to be how the hardware seems to time things. + if (micro <= 5) + micro = 10; + // Yes, this 7 is reproducible. 6 is (a lot) longer than 7. + else if (micro == 7) + micro = 15; + else if (micro <= 215) + micro = 250; + + CoreTiming::ScheduleEvent(usToCycles(micro), waitTimer, __KernelGetCurThread()); +} + +void __KernelMsgPipeInit() +{ + waitTimer = CoreTiming::RegisterEvent("MsgPipeTimeout", __KernelMsgPipeTimeout); +} + +void __KernelMsgPipeDoState(PointerWrap &p) +{ + p.Do(waitTimer); + CoreTiming::RestoreRegisterEvent(waitTimer, "MsgPipeTimeout", __KernelMsgPipeTimeout); + p.DoMarker("sceKernelMsgPipe"); +} + int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr) { if (!name) @@ -327,7 +391,8 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); + __KernelSetMsgPipeTimeout(timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); return; } } @@ -359,7 +424,8 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); + __KernelSetMsgPipeTimeout(timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); return; } } @@ -499,7 +565,8 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); + __KernelSetMsgPipeTimeout(timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); return; } } @@ -535,7 +602,8 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, 0, cbEnabled, "msgpipe waited"); + __KernelSetMsgPipeTimeout(timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); return; } } diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index fb873fa3c1..8c6a33d271 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -17,6 +17,8 @@ #pragma once +class PointerWrap; + int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr); int sceKernelDeleteMsgPipe(SceUID uid); void sceKernelSendMsgPipe(); @@ -28,4 +30,6 @@ void sceKernelTryReceiveMsgPipe(); int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr); void sceKernelReferMsgPipeStatus(); +void __KernelMsgPipeInit(); +void __KernelMsgPipeDoState(PointerWrap &p); KernelObject *__KernelMsgPipeObject(); From b06de3553661b9ca34fdd7d443c92025c24ad5fe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 09:48:43 -0700 Subject: [PATCH 10/26] Verify msgpipe threads are waiting before waking. --- Core/HLE/sceKernelMsgPipe.cpp | 55 ++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 9fc8e51a79..d1ba55f9ee 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -57,11 +57,17 @@ struct MsgPipeWaitingThread s32 waitMode; PSPPointer transferredBytes; - void Cancel(SceUID waitID, int result) + bool IsStillWaiting(SceUID waitID) const { u32 error; int actualWaitID = __KernelGetWaitID(id, WAITTYPE_MSGPIPE, error); - if (actualWaitID == waitID) + return actualWaitID == waitID; + } + + void WriteCurrentTimeout(SceUID waitID) const + { + u32 error; + if (IsStillWaiting(waitID)) { u32 timeoutPtr = __KernelGetWaitTimeoutPtr(id, error); if (timeoutPtr != 0 && waitTimer != -1) @@ -70,11 +76,24 @@ struct MsgPipeWaitingThread s64 cyclesLeft = CoreTiming::UnscheduleEvent(waitTimer, id); Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); } + } + } - *transferredBytes = 0; + void Complete(SceUID waitID, int result, u32 transferred = (u32)-1) const + { + if (IsStillWaiting(waitID)) + { + WriteCurrentTimeout(waitID); + if (transferred != (u32)-1) + *transferredBytes = transferred; __KernelResumeThreadFromWait(id, result); } } + + void Cancel(SceUID waitID, int result) const + { + Complete(waitID, result, 0); + } }; struct MsgPipe : public KernelObject @@ -135,9 +154,8 @@ struct MsgPipe : public KernelObject { // Put all the data to the buffer Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); - *thread->transferredBytes = thread->bufSize; nmp.freeSize -= thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(GetUID(), 0, thread->bufSize); sendWaitingThreads.erase(sendWaitingThreads.begin()); CheckReceiveThreads(); } @@ -145,9 +163,8 @@ struct MsgPipe : public KernelObject { // Put as much data as possible into the buffer Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); - *thread->transferredBytes = nmp.freeSize; nmp.freeSize = 0; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(GetUID(), 0, nmp.freeSize); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckReceiveThreads(); } @@ -165,9 +182,8 @@ struct MsgPipe : public KernelObject Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), thread->bufSize); // Put the unused data at the start of the buffer memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + thread->bufSize, nmp.bufSize - nmp.freeSize); - *thread->transferredBytes = thread->bufSize; nmp.freeSize += thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(GetUID(), 0, thread->bufSize); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckSendThreads(); } @@ -175,9 +191,8 @@ struct MsgPipe : public KernelObject { // Get all the data from the buffer Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), nmp.bufSize - nmp.freeSize); - *thread->transferredBytes = nmp.bufSize - nmp.freeSize; nmp.freeSize = nmp.bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(GetUID(), 0, nmp.bufSize - nmp.freeSize); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); CheckSendThreads(); } @@ -353,8 +368,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode sendSize = 0; if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { - *thread->transferredBytes = thread->bufSize - thread->freeSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize - thread->freeSize); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } break; @@ -362,8 +376,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode else if (thread->freeSize == sendSize) { Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), sendSize); - *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); curSendAddr += sendSize; sendSize = 0; @@ -374,8 +387,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), thread->freeSize); sendSize -= thread->freeSize; curSendAddr += thread->freeSize; - *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } } @@ -525,8 +537,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // The sending thread mode is ASAP: we have sent some data so restart it even though its buffer isn't empty if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { - *thread->transferredBytes = thread->bufSize - thread->freeSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize - thread->freeSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } break; @@ -535,8 +546,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int else if (thread->bufSize - thread->freeSize == receiveSize) { Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); - *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); curReceiveAddr += receiveSize; receiveSize = 0; @@ -548,8 +558,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), thread->bufSize - thread->freeSize); receiveSize -= thread->bufSize - thread->freeSize; curReceiveAddr += thread->bufSize - thread->freeSize; - *thread->transferredBytes = thread->bufSize; - __KernelResumeThreadFromWait(thread->id, 0); + thread->Complete(m->GetUID(), 0, thread->bufSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } } From 8a5dadcf53e878fd96365479c5883f31e1716366 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 09:52:15 -0700 Subject: [PATCH 11/26] Start out with 0 written msgpipe bytes. --- Core/HLE/sceKernelMsgPipe.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index d1ba55f9ee..1e835d8877 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -84,7 +84,7 @@ struct MsgPipeWaitingThread if (IsStillWaiting(waitID)) { WriteCurrentTimeout(waitID); - if (transferred != (u32)-1) + if (transferred != (u32)-1 && transferredBytes.IsValid()) *transferredBytes = transferred; __KernelResumeThreadFromWait(id, result); } @@ -114,6 +114,10 @@ struct MsgPipe : public KernelObject void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr, bool usePrio) { MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr }; + // Start out with 0 transferred bytes while waiting. + if (thread.transferredBytes.IsValid()) + *thread.transferredBytes = 0; + if (usePrio) { for (std::vector::iterator it = list.begin(); it != list.end(); it++) From 653e0f96299abe4bfda519878d0b6c993d282f14 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 10:09:21 -0700 Subject: [PATCH 12/26] Don't wait on a msgpipe when timeout <= 2. --- Core/HLE/sceKernelMsgPipe.cpp | 44 ++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 1e835d8877..837593e9fc 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -246,24 +246,22 @@ void __KernelMsgPipeTimeout(u64 userdata, int cyclesLate) } } -void __KernelSetMsgPipeTimeout(u32 timeoutPtr) +bool __KernelSetMsgPipeTimeout(u32 timeoutPtr) { if (timeoutPtr == 0 || waitTimer == -1) - return; + return true; int micro = (int) Memory::Read_U32(timeoutPtr); + if (micro <= 2) + { + // Don't wait or reschedule, just timeout immediately. + return false; + } - // TODO: Correct. - // This happens to be how the hardware seems to time things. - if (micro <= 5) - micro = 10; - // Yes, this 7 is reproducible. 6 is (a lot) longer than 7. - else if (micro == 7) - micro = 15; - else if (micro <= 215) + if (micro <= 210) micro = 250; - CoreTiming::ScheduleEvent(usToCycles(micro), waitTimer, __KernelGetCurThread()); + return true; } void __KernelMsgPipeInit() @@ -407,8 +405,10 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelSetMsgPipeTimeout(timeoutPtr); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + if (__KernelSetMsgPipeTimeout(timeoutPtr)) + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + else + RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); return; } } @@ -440,8 +440,10 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); RETURN(0); - __KernelSetMsgPipeTimeout(timeoutPtr); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + if (__KernelSetMsgPipeTimeout(timeoutPtr)) + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + else + RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); return; } } @@ -578,8 +580,10 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelSetMsgPipeTimeout(timeoutPtr); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + if (__KernelSetMsgPipeTimeout(timeoutPtr)) + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + else + RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); return; } } @@ -615,8 +619,10 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); RETURN(0); - __KernelSetMsgPipeTimeout(timeoutPtr); - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + if (__KernelSetMsgPipeTimeout(timeoutPtr)) + __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + else + RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); return; } } From 4be06d2432c32b3da5702b37d4325b843a9141b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 13:17:12 -0700 Subject: [PATCH 13/26] Wrap the msgpipe send functions. --- Core/HLE/FunctionWrappers.h | 5 +++ Core/HLE/sceKernel.cpp | 6 +-- Core/HLE/sceKernelMemory.cpp | 1 - Core/HLE/sceKernelMsgPipe.cpp | 70 +++++++++++------------------------ Core/HLE/sceKernelMsgPipe.h | 6 +-- 5 files changed, 32 insertions(+), 56 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index ea5e6c18f3..4e70a62601 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -605,6 +605,11 @@ template void WrapI_IUUUU() { RETURN(retval); } +template void WrapI_IUUUUU() { + int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); + RETURN(retval); +} + template void WrapI_IUII() { int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 7853dba24d..dab634b0dd 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -759,9 +759,9 @@ const HLEFunction ThreadManForUser[] = {0x7C0DC2A0,WrapI_CIUUU, "sceKernelCreateMsgPipe"}, {0xF0B7DA1C,WrapI_I, "sceKernelDeleteMsgPipe"}, - {0x876DBFAD,sceKernelSendMsgPipe,"sceKernelSendMsgPipe"}, - {0x7C41F2C2,sceKernelSendMsgPipeCB,"sceKernelSendMsgPipeCB"}, - {0x884C9F90,sceKernelTrySendMsgPipe,"sceKernelTrySendMsgPipe"}, + {0x876DBFAD,WrapI_IUUUUU, "sceKernelSendMsgPipe"}, + {0x7C41F2C2,WrapI_IUUUUU, "sceKernelSendMsgPipeCB"}, + {0x884C9F90,WrapI_IUUUU, "sceKernelTrySendMsgPipe"}, {0x74829B76,sceKernelReceiveMsgPipe,"sceKernelReceiveMsgPipe"}, {0xFBFA697D,sceKernelReceiveMsgPipeCB,"sceKernelReceiveMsgPipeCB"}, {0xDF52098F,sceKernelTryReceiveMsgPipe,"sceKernelTryReceiveMsgPipe"}, diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 7bce80373d..48ab2bdffb 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -1168,7 +1168,6 @@ int sceKernelFreeVpl(SceUID uid, u32 addr) { if (vpl->alloc.FreeExact(addr)) { - // TODO: smallest priority if ((vpl->nv.attr & PSP_VPL_ATTR_PRIORITY) != 0) std::stable_sort(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), __VplThreadSortPriority); diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 837593e9fc..2bb6daa5bb 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -15,6 +15,8 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include + #include "Core/Reporting.h" #include "Core/CoreTiming.h" #include "Core/HLE/HLE.h" @@ -354,7 +356,7 @@ int sceKernelDeleteMsgPipe(SceUID uid) return kernelObjects.Destroy(uid); } -void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) +int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curSendAddr = sendBufAddr; if (m->nmp.bufSize == 0) @@ -397,19 +399,15 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode if (sendSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curSendAddr == sendBufAddr)) { if (poll) - { - RETURN(SCE_KERNEL_ERROR_MPP_FULL); - return; - } + return SCE_KERNEL_ERROR_MPP_FULL; else { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); - RETURN(0); if (__KernelSetMsgPipeTimeout(timeoutPtr)) __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); else - RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); - return; + return SCE_KERNEL_ERROR_WAIT_TIMEOUT; + return 0; } } } @@ -432,19 +430,15 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode else { if (poll) - { - RETURN(SCE_KERNEL_ERROR_MPP_FULL); - return; - } + return SCE_KERNEL_ERROR_MPP_FULL; else { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); - RETURN(0); if (__KernelSetMsgPipeTimeout(timeoutPtr)) __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); else - RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); - return; + return SCE_KERNEL_ERROR_WAIT_TIMEOUT; + return 0; } } @@ -455,70 +449,48 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode } Memory::Write_U32(curSendAddr - sendBufAddr, resultAddr); - RETURN(0); + return 0; } -void sceKernelSendMsgPipe() +int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - SceUInt uid = PARAM(0); - u32 sendBufAddr = PARAM(1); - u32 sendSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 timeoutPtr = PARAM(5); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelSendMsgPipe(id=%i, addr=%08x, size=%i, mode=%i, result=%08x, timeout=%08x)", uid, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr); - __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, false, false); + return __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, false, false); } -void sceKernelSendMsgPipeCB() +int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - SceUInt uid = PARAM(0); - u32 sendBufAddr = PARAM(1); - u32 sendSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 timeoutPtr = PARAM(5); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipeCB(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelSendMsgPipeCB(id=%i, addr=%08x, size=%i, mode=%i, result=%08x, timeout=%08x)", uid, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr); - __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, true, false); - __KernelCheckCallbacks(); + // TODO: Verify callback behavior. + hleCheckCurrentCallbacks(); + return __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, true, false); } -void sceKernelTrySendMsgPipe() +int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr) { - SceUInt uid = PARAM(0); - u32 sendBufAddr = PARAM(1); - u32 sendSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTrySendMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelTrySendMsgPipe(id=%i, addr=%08x, size=%i, mode=%i, result=%08x)", uid, sendBufAddr, sendSize, waitMode, resultAddr); - __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, 0, false, true); + return __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, 0, false, true); } void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index 8c6a33d271..f96e877372 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -21,9 +21,9 @@ class PointerWrap; int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, u32 optionsPtr); int sceKernelDeleteMsgPipe(SceUID uid); -void sceKernelSendMsgPipe(); -void sceKernelSendMsgPipeCB(); -void sceKernelTrySendMsgPipe(); +int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); +int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); +int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr); void sceKernelReceiveMsgPipe(); void sceKernelReceiveMsgPipeCB(); void sceKernelTryReceiveMsgPipe(); From 27268967f962c9174ee01d25b0003eb9a4c96c42 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 13:24:30 -0700 Subject: [PATCH 14/26] Sort msgpipe waits while waking (like others.) --- Core/HLE/sceKernelMsgPipe.cpp | 70 +++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 2bb6daa5bb..71496048f9 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -96,8 +96,28 @@ struct MsgPipeWaitingThread { Complete(waitID, result, 0); } + + void ReadBuffer(u8 *dest, u32 len) + { + Memory::Memcpy(dest, bufAddr, len); + if (transferredBytes.IsValid()) + *transferredBytes += len; + } + + void WriteBuffer(const u8 *src, u32 len) + { + Memory::Memcpy(bufAddr + (bufSize - freeSize), src, len); + freeSize -= len; + if (transferredBytes.IsValid()) + *transferredBytes += len; + } }; +bool __KernelMsgPipeThreadSortPriority(MsgPipeWaitingThread thread1, MsgPipeWaitingThread thread2) +{ + return __KernelThreadSortPriority(thread1.id, thread2.id); +} + struct MsgPipe : public KernelObject { const char *GetName() {return nmp.name;} @@ -113,46 +133,30 @@ struct MsgPipe : public KernelObject userMemory.Free(buffer); } - void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr, bool usePrio) + void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr) { MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr }; // Start out with 0 transferred bytes while waiting. if (thread.transferredBytes.IsValid()) *thread.transferredBytes = 0; - if (usePrio) - { - for (std::vector::iterator it = list.begin(); it != list.end(); it++) - { - if (__KernelGetThreadPrio(id) >= __KernelGetThreadPrio((*it).id)) - { - list.insert(it, thread); - return; - } - } - - list.push_back(thread); - } - else - { - list.push_back(thread); - } + list.push_back(thread); } void AddSendWaitingThread(SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr) { - bool usePrio = ((nmp.attr & SCE_KERNEL_MPA_THPRI_S) != 0); - AddWaitingThread(sendWaitingThreads, id, addr, size, waitMode, transferredBytesAddr, usePrio); + AddWaitingThread(sendWaitingThreads, id, addr, size, waitMode, transferredBytesAddr); } void AddReceiveWaitingThread(SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr) { - bool usePrio = ((nmp.attr & SCE_KERNEL_MPA_THPRI_R) != 0); - AddWaitingThread(receiveWaitingThreads, id, addr, size, waitMode, transferredBytesAddr, usePrio); + AddWaitingThread(receiveWaitingThreads, id, addr, size, waitMode, transferredBytesAddr); } void CheckSendThreads() { + SortSendThreads(); + if (sendWaitingThreads.empty()) return; MsgPipeWaitingThread *thread = &sendWaitingThreads.front(); @@ -179,6 +183,8 @@ struct MsgPipe : public KernelObject // This function should be only ran when the temporary buffer size is not 0 (otherwise, data is copied directly to the threads) void CheckReceiveThreads() { + SortReceiveThreads(); + if (receiveWaitingThreads.empty()) return; MsgPipeWaitingThread *thread = &receiveWaitingThreads.front(); @@ -204,6 +210,20 @@ struct MsgPipe : public KernelObject } } + void SortReceiveThreads() + { + bool usePrio = (nmp.attr & SCE_KERNEL_MPA_THPRI_R) != 0; + if (usePrio) + std::stable_sort(receiveWaitingThreads.begin(), receiveWaitingThreads.end(), __KernelMsgPipeThreadSortPriority); + } + + void SortSendThreads() + { + bool usePrio = (nmp.attr & SCE_KERNEL_MPA_THPRI_S) != 0; + if (usePrio) + std::stable_sort(sendWaitingThreads.begin(), sendWaitingThreads.end(), __KernelMsgPipeThreadSortPriority); + } + virtual void DoState(PointerWrap &p) { p.Do(nmp); @@ -359,6 +379,8 @@ int sceKernelDeleteMsgPipe(SceUID uid) int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curSendAddr = sendBufAddr; + SceUID uid = m->GetUID(); + if (m->nmp.bufSize == 0) { while (!m->receiveWaitingThreads.empty()) @@ -404,7 +426,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); if (__KernelSetMsgPipeTimeout(timeoutPtr)) - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, uid, 0, timeoutPtr, cbEnabled, "msgpipe send waited"); else return SCE_KERNEL_ERROR_WAIT_TIMEOUT; return 0; @@ -435,7 +457,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); if (__KernelSetMsgPipeTimeout(timeoutPtr)) - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, uid, 0, timeoutPtr, cbEnabled, "msgpipe send waited"); else return SCE_KERNEL_ERROR_WAIT_TIMEOUT; return 0; From 23625eec30782932e66b80e31caf2757c3800344 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 13:27:28 -0700 Subject: [PATCH 15/26] Simplify and fix msgpipe send queuing logic. Should reschedule, should wait in line, couple error messages. --- Core/HLE/sceKernelMsgPipe.cpp | 199 ++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 84 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 71496048f9..81f78bbe83 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -133,10 +133,16 @@ struct MsgPipe : public KernelObject userMemory.Free(buffer); } + u32 GetUsedSize() + { + return (u32)(nmp.bufSize - nmp.freeSize); + } + void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr) { MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr }; // Start out with 0 transferred bytes while waiting. + // TODO: for receive, it might be a different (partial) number. if (thread.transferredBytes.IsValid()) *thread.transferredBytes = 0; @@ -153,61 +159,75 @@ struct MsgPipe : public KernelObject AddWaitingThread(receiveWaitingThreads, id, addr, size, waitMode, transferredBytesAddr); } - void CheckSendThreads() + bool CheckSendThreads() { SortSendThreads(); - if (sendWaitingThreads.empty()) - return; - MsgPipeWaitingThread *thread = &sendWaitingThreads.front(); - if ((u32) nmp.freeSize >= thread->bufSize) + bool wokeThreads = false; + bool filledSpace = false; + while (!sendWaitingThreads.empty() && nmp.freeSize > 0) { - // Put all the data to the buffer - Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); - nmp.freeSize -= thread->bufSize; - thread->Complete(GetUID(), 0, thread->bufSize); - sendWaitingThreads.erase(sendWaitingThreads.begin()); - CheckReceiveThreads(); - } - else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != 0) - { - // Put as much data as possible into the buffer - Memory::Memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), nmp.freeSize); - nmp.freeSize = 0; - thread->Complete(GetUID(), 0, nmp.freeSize); - receiveWaitingThreads.erase(receiveWaitingThreads.begin()); - CheckReceiveThreads(); + MsgPipeWaitingThread *thread = &sendWaitingThreads.front(); + u32 bytesToSend = 0; + if (thread->bufSize <= (u32) nmp.freeSize) + bytesToSend = thread->bufSize; + else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != 0) + bytesToSend = nmp.freeSize; + + if (bytesToSend != 0) + { + thread->ReadBuffer(Memory::GetPointer(buffer + GetUsedSize()), bytesToSend); + thread->Complete(GetUID(), 0); + sendWaitingThreads.erase(sendWaitingThreads.begin()); + wokeThreads = true; + filledSpace = true; + } + // Unlike receives, we don't do partial sends. Stop at first blocked thread. + else + break; } + + if (filledSpace) + wokeThreads |= CheckReceiveThreads(); + + return wokeThreads; } // This function should be only ran when the temporary buffer size is not 0 (otherwise, data is copied directly to the threads) - void CheckReceiveThreads() + bool CheckReceiveThreads() { SortReceiveThreads(); - if (receiveWaitingThreads.empty()) - return; - MsgPipeWaitingThread *thread = &receiveWaitingThreads.front(); - if ((u32) nmp.bufSize - (u32) nmp.freeSize >= thread->bufSize) + bool wokeThreads = false; + bool freedSpace = false; + while (!receiveWaitingThreads.empty() && GetUsedSize() > 0) { - // Get the needed data from the buffer - Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), thread->bufSize); - // Put the unused data at the start of the buffer - memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + thread->bufSize, nmp.bufSize - nmp.freeSize); - nmp.freeSize += thread->bufSize; - thread->Complete(GetUID(), 0, thread->bufSize); - receiveWaitingThreads.erase(receiveWaitingThreads.begin()); - CheckSendThreads(); - } - else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != nmp.bufSize) - { - // Get all the data from the buffer - Memory::Memcpy(thread->bufAddr, Memory::GetPointer(buffer), nmp.bufSize - nmp.freeSize); - nmp.freeSize = nmp.bufSize; - thread->Complete(GetUID(), 0, nmp.bufSize - nmp.freeSize); - receiveWaitingThreads.erase(receiveWaitingThreads.begin()); - CheckSendThreads(); + MsgPipeWaitingThread *thread = &receiveWaitingThreads.front(); + // Receive as much as possible, even if it's not enough to wake up. + u32 bytesToSend = std::min(thread->freeSize, GetUsedSize()); + + thread->WriteBuffer(Memory::GetPointer(buffer), bytesToSend); + // Put the unused data at the start of the buffer. + nmp.freeSize += bytesToSend; + memmove(Memory::GetPointer(buffer), Memory::GetPointer(buffer) + bytesToSend, GetUsedSize()); + freedSpace = true; + + if (thread->waitMode == SCE_KERNEL_MPW_ASAP || thread->freeSize == 0) + { + thread->Complete(GetUID(), 0, thread->bufSize); + receiveWaitingThreads.erase(receiveWaitingThreads.begin()); + wokeThreads = true; + thread = NULL; + } + // Stop at the first that can't wake up. + else + break; } + + if (freedSpace) + wokeThreads |= CheckSendThreads(); + + return wokeThreads; } void SortReceiveThreads() @@ -381,42 +401,43 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 curSendAddr = sendBufAddr; SceUID uid = m->GetUID(); + if (sendSize & 0x80000000) + { + ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): illegal size %d", uid, sendSize); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } + + // If the buffer size is 0, nothing is buffered and all operations wait. if (m->nmp.bufSize == 0) { - while (!m->receiveWaitingThreads.empty()) + m->SortReceiveThreads(); + + while (!m->receiveWaitingThreads.empty() && sendSize != 0) { MsgPipeWaitingThread *thread = &m->receiveWaitingThreads.front(); - if (thread->freeSize > sendSize) + if (!thread->IsStillWaiting(uid)) { - Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), sendSize); - thread->freeSize -= sendSize; - curSendAddr += sendSize; - sendSize = 0; - if (thread->waitMode == SCE_KERNEL_MPW_ASAP) + m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); + continue; + } + + u32 bytesToSend = std::min(thread->freeSize, sendSize); + if (bytesToSend > 0) + { + thread->WriteBuffer(Memory::GetPointer(curSendAddr), bytesToSend); + sendSize -= bytesToSend; + curSendAddr += bytesToSend; + + if (thread->freeSize == 0 || thread->waitMode == SCE_KERNEL_MPW_ASAP) { - thread->Complete(m->GetUID(), 0, thread->bufSize - thread->freeSize); + thread->Complete(uid, 0); m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); + hleReSchedule(cbEnabled, "msgpipe data sent"); + thread = NULL; } - break; - } - else if (thread->freeSize == sendSize) - { - Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), sendSize); - thread->Complete(m->GetUID(), 0, thread->bufSize); - m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); - curSendAddr += sendSize; - sendSize = 0; - break; - } - else - { - Memory::Memcpy(thread->bufAddr + (thread->bufSize - thread->freeSize), Memory::GetPointer(curSendAddr), thread->freeSize); - sendSize -= thread->freeSize; - curSendAddr += thread->freeSize; - thread->Complete(m->GetUID(), 0, thread->bufSize); - m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); } } + // If there is still data to send and (we want to send all of it or we didn't send anything) if (sendSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curSendAddr == sendBufAddr)) { @@ -435,19 +456,31 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, } else { - if (sendSize <= (u32) m->nmp.freeSize) + if (sendSize > (u32) m->nmp.bufSize) { - Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), sendSize); - m->nmp.freeSize -= sendSize; - curSendAddr = sendBufAddr + sendSize; - sendSize = 0; + ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): size %d too large for buffer", uid, sendSize); + return SCE_KERNEL_ERROR_ILLEGAL_SIZE; } - else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != 0) + + u32 bytesToSend = 0; + // If others are already waiting, space or not, we have to get in line. + if (m->sendWaitingThreads.empty()) { - Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), m->nmp.freeSize); - curSendAddr = sendBufAddr + m->nmp.freeSize; - sendSize -= m->nmp.freeSize; - m->nmp.freeSize = 0; + if (sendSize <= (u32) m->nmp.freeSize) + bytesToSend = sendSize; + else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != 0) + bytesToSend = m->nmp.freeSize; + } + + if (bytesToSend != 0) + { + Memory::Memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), bytesToSend); + m->nmp.freeSize -= bytesToSend; + curSendAddr += bytesToSend; + sendSize -= bytesToSend; + + if (m->CheckReceiveThreads()) + hleReSchedule(cbEnabled, "msgpipe data sent"); } else { @@ -463,13 +496,11 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, return 0; } } - - if (curSendAddr != sendBufAddr) - { - m->CheckReceiveThreads(); - } } - Memory::Write_U32(curSendAddr - sendBufAddr, resultAddr); + + // We didn't wait, so update the number of bytes transferred now. + if (Memory::IsValidAddress(resultAddr)) + Memory::Write_U32(curSendAddr - sendBufAddr, resultAddr); return 0; } From 29067edf52b41ed116f6e53e9422b7f7495dc266 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 14:18:48 -0700 Subject: [PATCH 16/26] When sorting, also clear not waiting threads. --- Core/HLE/sceKernelMsgPipe.cpp | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 81f78bbe83..224fce5e84 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -232,6 +232,20 @@ struct MsgPipe : public KernelObject void SortReceiveThreads() { + // Clean up any not waiting at the same time. + size_t size = receiveWaitingThreads.size(); + for (size_t i = 0; i < size; ++i) + { + if (!receiveWaitingThreads[i].IsStillWaiting(GetUID())) + { + // Decrement size and swap what was there with i. + std::swap(receiveWaitingThreads[i], receiveWaitingThreads[--size]); + // Now we haven't checked the new i, so go back and do i again. + --i; + } + } + receiveWaitingThreads.resize(size); + bool usePrio = (nmp.attr & SCE_KERNEL_MPA_THPRI_R) != 0; if (usePrio) std::stable_sort(receiveWaitingThreads.begin(), receiveWaitingThreads.end(), __KernelMsgPipeThreadSortPriority); @@ -239,6 +253,20 @@ struct MsgPipe : public KernelObject void SortSendThreads() { + // Clean up any not waiting at the same time. + size_t size = sendWaitingThreads.size(); + for (size_t i = 0; i < size; ++i) + { + if (!sendWaitingThreads[i].IsStillWaiting(GetUID())) + { + // Decrement size and swap what was there with i. + std::swap(sendWaitingThreads[i], sendWaitingThreads[--size]); + // Now we haven't checked the new i, so go back and do i again. + --i; + } + } + sendWaitingThreads.resize(size); + bool usePrio = (nmp.attr & SCE_KERNEL_MPA_THPRI_S) != 0; if (usePrio) std::stable_sort(sendWaitingThreads.begin(), sendWaitingThreads.end(), __KernelMsgPipeThreadSortPriority); @@ -415,11 +443,6 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, while (!m->receiveWaitingThreads.empty() && sendSize != 0) { MsgPipeWaitingThread *thread = &m->receiveWaitingThreads.front(); - if (!thread->IsStillWaiting(uid)) - { - m->receiveWaitingThreads.erase(m->receiveWaitingThreads.begin()); - continue; - } u32 bytesToSend = std::min(thread->freeSize, sendSize); if (bytesToSend > 0) @@ -464,6 +487,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 bytesToSend = 0; // If others are already waiting, space or not, we have to get in line. + m->SortSendThreads(); if (m->sendWaitingThreads.empty()) { if (sendSize <= (u32) m->nmp.freeSize) From 769bac3acfec045177f3c9b848738541e207a562 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 14:22:46 -0700 Subject: [PATCH 17/26] Fix send of 0 bytes, more error handling. --- Core/HLE/sceKernelMsgPipe.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 224fce5e84..6eb7ec588c 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -435,6 +435,18 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, return SCE_KERNEL_ERROR_ILLEGAL_ADDR; } + if (sendSize != 0 && !Memory::IsValidAddress(sendBufAddr)) + { + ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): bad buffer address %08x (should crash?)", uid, sendBufAddr); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } + + if (waitMode != SCE_KERNEL_MPW_ASAP && waitMode != SCE_KERNEL_MPW_FULL) + { + ERROR_LOG(HLE, "__KernelSendMsgPipe(%d): invalid wait mode", uid, waitMode); + return SCE_KERNEL_ERROR_ILLEGAL_MODE; + } + // If the buffer size is 0, nothing is buffered and all operations wait. if (m->nmp.bufSize == 0) { @@ -506,7 +518,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, if (m->CheckReceiveThreads()) hleReSchedule(cbEnabled, "msgpipe data sent"); } - else + else if (sendSize != 0) { if (poll) return SCE_KERNEL_ERROR_MPP_FULL; From 6750794c8aab743d3e07c4264d9d5a92737b580d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 14:57:30 -0700 Subject: [PATCH 18/26] Fix a weird sceKernelTrySendMsgPipe() edge case. --- Core/HLE/sceKernelMsgPipe.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 6eb7ec588c..c385081a77 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -477,7 +477,12 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, if (sendSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curSendAddr == sendBufAddr)) { if (poll) + { + // Generally, result is not set to 0 in this case. But for a 0 size buffer in ASAP mode, it is. + if (Memory::IsValidAddress(resultAddr) && waitMode == SCE_KERNEL_MPW_ASAP) + Memory::Write_U32(curSendAddr - sendBufAddr, resultAddr); return SCE_KERNEL_ERROR_MPP_FULL; + } else { m->AddSendWaitingThread(__KernelGetCurThread(), curSendAddr, sendSize, waitMode, resultAddr); From e2f0dfe243d6ceed1ea594a818ea2ece406df173 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 15:16:06 -0700 Subject: [PATCH 19/26] Wrap sceKernelReceiveMsgPipe() and friends. --- Core/HLE/sceKernel.cpp | 6 ++-- Core/HLE/sceKernelMsgPipe.cpp | 67 ++++++++++------------------------- Core/HLE/sceKernelMsgPipe.h | 6 ++-- 3 files changed, 25 insertions(+), 54 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index dab634b0dd..a729fa6a76 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -762,9 +762,9 @@ const HLEFunction ThreadManForUser[] = {0x876DBFAD,WrapI_IUUUUU, "sceKernelSendMsgPipe"}, {0x7C41F2C2,WrapI_IUUUUU, "sceKernelSendMsgPipeCB"}, {0x884C9F90,WrapI_IUUUU, "sceKernelTrySendMsgPipe"}, - {0x74829B76,sceKernelReceiveMsgPipe,"sceKernelReceiveMsgPipe"}, - {0xFBFA697D,sceKernelReceiveMsgPipeCB,"sceKernelReceiveMsgPipeCB"}, - {0xDF52098F,sceKernelTryReceiveMsgPipe,"sceKernelTryReceiveMsgPipe"}, + {0x74829B76,WrapI_IUUUUU, "sceKernelReceiveMsgPipe"}, + {0xFBFA697D,WrapI_IUUUUU, "sceKernelReceiveMsgPipeCB"}, + {0xDF52098F,WrapI_IUUUU, "sceKernelTryReceiveMsgPipe"}, {0x349B864D,WrapI_IUU, "sceKernelCancelMsgPipe"}, {0x33BE4024,sceKernelReferMsgPipeStatus,"sceKernelReferMsgPipeStatus"}, diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index c385081a77..c24ac1e2a5 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -587,7 +587,7 @@ int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitM return __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, 0, false, true); } -void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) +int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curReceiveAddr = receiveBufAddr; // MsgPipe buffer size is 0, receiving directly from waiting send threads @@ -638,19 +638,15 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int if (receiveSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curReceiveAddr == receiveBufAddr)) { if (poll) - { - RETURN(SCE_KERNEL_ERROR_MPP_EMPTY); - return; - } + return SCE_KERNEL_ERROR_MPP_EMPTY; else { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); - RETURN(0); if (__KernelSetMsgPipeTimeout(timeoutPtr)) __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); else - RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); - return; + return SCE_KERNEL_ERROR_WAIT_TIMEOUT; + return 0; } } } @@ -677,19 +673,15 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int else { if (poll) - { - RETURN(SCE_KERNEL_ERROR_MPP_EMPTY); - return; - } + return SCE_KERNEL_ERROR_MPP_EMPTY; else { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); - RETURN(0); if (__KernelSetMsgPipeTimeout(timeoutPtr)) __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); else - RETURN(SCE_KERNEL_ERROR_WAIT_TIMEOUT); - return; + return SCE_KERNEL_ERROR_WAIT_TIMEOUT; + return 0; } } @@ -700,69 +692,48 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int } Memory::Write_U32(curReceiveAddr - receiveBufAddr, resultAddr); - RETURN(0); + return 0; } -void sceKernelReceiveMsgPipe() +int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - SceUID uid = PARAM(0); - u32 receiveBufAddr = PARAM(1); - u32 receiveSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 timeoutPtr = PARAM(5); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelReceiveMsgPipe(%i, %08x, %i, %i, %08x, %08x)", uid, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr); - __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr, false, false); + return __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr, false, false); } -void sceKernelReceiveMsgPipeCB() +int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - SceUID uid = PARAM(0); - u32 receiveBufAddr = PARAM(1); - u32 receiveSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 timeoutPtr = PARAM(5); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipeCB(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelReceiveMsgPipeCB(%i, %08x, %i, %i, %08x, %08x)", uid, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr); - __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr, true, false); + // TODO: Verify callback behavior. + hleCheckCurrentCallbacks(); + return __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr, true, false); } -void sceKernelTryReceiveMsgPipe() +int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr) { - SceUID uid = PARAM(0); - u32 receiveBufAddr = PARAM(1); - u32 receiveSize = PARAM(2); - int waitMode = PARAM(3); - u32 resultAddr = PARAM(4); - u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTryReceiveMsgPipe(%i) - ERROR %08x", uid, error); - RETURN(error); - return; + return error; } DEBUG_LOG(HLE, "sceKernelTryReceiveMsgPipe(%i, %08x, %i, %i, %08x)", uid, receiveBufAddr, receiveSize, waitMode, resultAddr); - __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, 0, false, true); + return __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, 0, false, true); } int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr) diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index f96e877372..b80df69467 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -24,9 +24,9 @@ int sceKernelDeleteMsgPipe(SceUID uid); int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr); -void sceKernelReceiveMsgPipe(); -void sceKernelReceiveMsgPipeCB(); -void sceKernelTryReceiveMsgPipe(); +int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); +int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); +int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr); int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr); void sceKernelReferMsgPipeStatus(); From b7ea35b71d57f5b1f8555cdeb1baf4532387e602 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 15:26:02 -0700 Subject: [PATCH 20/26] Add some error checking to msgpipe receives. --- Core/HLE/sceKernelMsgPipe.cpp | 40 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index c24ac1e2a5..00923c6ac6 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -590,6 +590,26 @@ int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitM int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { u32 curReceiveAddr = receiveBufAddr; + SceUID uid = m->GetUID(); + + if (receiveSize & 0x80000000) + { + ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): illegal size %d", uid, receiveSize); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } + + if (receiveSize != 0 && !Memory::IsValidAddress(receiveBufAddr)) + { + ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): bad buffer address %08x (should crash?)", uid, receiveBufAddr); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } + + if (waitMode != SCE_KERNEL_MPW_ASAP && waitMode != SCE_KERNEL_MPW_FULL) + { + ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): invalid wait mode", uid, waitMode); + return SCE_KERNEL_ERROR_ILLEGAL_MODE; + } + // MsgPipe buffer size is 0, receiving directly from waiting send threads if (m->nmp.bufSize == 0) { @@ -609,7 +629,7 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // The sending thread mode is ASAP: we have sent some data so restart it even though its buffer isn't empty if (thread->waitMode == SCE_KERNEL_MPW_ASAP) { - thread->Complete(m->GetUID(), 0, thread->bufSize - thread->freeSize); + thread->Complete(uid, 0, thread->bufSize - thread->freeSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } break; @@ -618,7 +638,7 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int else if (thread->bufSize - thread->freeSize == receiveSize) { Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); - thread->Complete(m->GetUID(), 0, thread->bufSize); + thread->Complete(uid, 0, thread->bufSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); curReceiveAddr += receiveSize; receiveSize = 0; @@ -630,7 +650,7 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), thread->bufSize - thread->freeSize); receiveSize -= thread->bufSize - thread->freeSize; curReceiveAddr += thread->bufSize - thread->freeSize; - thread->Complete(m->GetUID(), 0, thread->bufSize); + thread->Complete(uid, 0, thread->bufSize); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } } @@ -643,7 +663,7 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); if (__KernelSetMsgPipeTimeout(timeoutPtr)) - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, uid, 0, timeoutPtr, cbEnabled, "msgpipe receive waited"); else return SCE_KERNEL_ERROR_WAIT_TIMEOUT; return 0; @@ -653,6 +673,12 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // Getting data from the MsgPipe buffer else { + if (receiveSize > (u32) m->nmp.bufSize) + { + ERROR_LOG(HLE, "__KernelReceiveMsgPipe(%d): size %d too large for buffer", uid, receiveSize); + return SCE_KERNEL_ERROR_ILLEGAL_SIZE; + } + // Enough data in the buffer: copy just the needed amount of data if (receiveSize <= (u32) m->nmp.bufSize - (u32) m->nmp.freeSize) { @@ -678,7 +704,7 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); if (__KernelSetMsgPipeTimeout(timeoutPtr)) - __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), 0, timeoutPtr, cbEnabled, "msgpipe waited"); + __KernelWaitCurThread(WAITTYPE_MSGPIPE, uid, 0, timeoutPtr, cbEnabled, "msgpipe receive waited"); else return SCE_KERNEL_ERROR_WAIT_TIMEOUT; return 0; @@ -690,7 +716,9 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int m->CheckSendThreads(); } } - Memory::Write_U32(curReceiveAddr - receiveBufAddr, resultAddr); + + if (Memory::IsValidAddress(resultAddr)) + Memory::Write_U32(curReceiveAddr - receiveBufAddr, resultAddr); return 0; } From e6236a1d31d5546930bc04de2acaff9285d0f1c8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 16:32:05 -0700 Subject: [PATCH 21/26] Fix sceKernelReceiveMsgPipe() with no buffer. And simplify, reschedule correctly. --- Core/HLE/sceKernelMsgPipe.cpp | 92 +++++++++++++++-------------------- 1 file changed, 39 insertions(+), 53 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 00923c6ac6..be5133dde3 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -55,6 +55,7 @@ struct MsgPipeWaitingThread SceUID id; u32 bufAddr; u32 bufSize; + // Free space at the end for receive, valid/free to read bytes from end for send. u32 freeSize; s32 waitMode; PSPPointer transferredBytes; @@ -99,7 +100,8 @@ struct MsgPipeWaitingThread void ReadBuffer(u8 *dest, u32 len) { - Memory::Memcpy(dest, bufAddr, len); + Memory::Memcpy(dest, bufAddr + bufSize - freeSize, len); + freeSize -= len; if (transferredBytes.IsValid()) *transferredBytes += len; } @@ -509,7 +511,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, { if (sendSize <= (u32) m->nmp.freeSize) bytesToSend = sendSize; - else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != 0) + else if (waitMode == SCE_KERNEL_MPW_ASAP) bytesToSend = m->nmp.freeSize; } @@ -613,47 +615,31 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int // MsgPipe buffer size is 0, receiving directly from waiting send threads if (m->nmp.bufSize == 0) { + m->SortSendThreads(); + // While they're still sending waiting threads (which can send data) - while (!m->sendWaitingThreads.empty()) + while (!m->sendWaitingThreads.empty() && receiveSize != 0) { MsgPipeWaitingThread *thread = &m->sendWaitingThreads.front(); - // Sending thread has more data than we have to receive: retrieve just the amount of data we want - if (thread->bufSize - thread->freeSize > receiveSize) + + // For send threads, "freeSize" is "free to be read". + u32 bytesToReceive = std::min(thread->freeSize, receiveSize); + if (bytesToReceive > 0) { - Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); - thread->freeSize += receiveSize; - // Move still available data at the beginning of the sending thread buffer - Memory::Memcpy(thread->bufAddr, Memory::GetPointer(thread->bufAddr + receiveSize), thread->bufSize - thread->freeSize); - curReceiveAddr += receiveSize; - receiveSize = 0; - // The sending thread mode is ASAP: we have sent some data so restart it even though its buffer isn't empty - if (thread->waitMode == SCE_KERNEL_MPW_ASAP) + thread->ReadBuffer(Memory::GetPointer(curReceiveAddr), bytesToReceive); + receiveSize -= bytesToReceive; + curReceiveAddr += bytesToReceive; + + if (thread->freeSize == 0 || thread->waitMode == SCE_KERNEL_MPW_ASAP) { - thread->Complete(uid, 0, thread->bufSize - thread->freeSize); + thread->Complete(uid, 0); m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); + hleReSchedule(cbEnabled, "msgpipe data received"); + thread = NULL; } - break; - } - // Sending thread wants to send the same amount of data as we want to retrieve: get the data and resume thread - else if (thread->bufSize - thread->freeSize == receiveSize) - { - Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), receiveSize); - thread->Complete(uid, 0, thread->bufSize); - m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); - curReceiveAddr += receiveSize; - receiveSize = 0; - break; - } - // Not enough data in the sending thread: get the data available and restart the sending thread, then loop - else - { - Memory::Memcpy(curReceiveAddr, Memory::GetPointer(thread->bufAddr), thread->bufSize - thread->freeSize); - receiveSize -= thread->bufSize - thread->freeSize; - curReceiveAddr += thread->bufSize - thread->freeSize; - thread->Complete(uid, 0, thread->bufSize); - m->sendWaitingThreads.erase(m->sendWaitingThreads.begin()); } } + // All data hasn't been received and (mode isn't ASAP or nothing was received) if (receiveSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curReceiveAddr == receiveBufAddr)) { @@ -679,24 +665,29 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int return SCE_KERNEL_ERROR_ILLEGAL_SIZE; } - // Enough data in the buffer: copy just the needed amount of data - if (receiveSize <= (u32) m->nmp.bufSize - (u32) m->nmp.freeSize) + u32 bytesToReceive = 0; + // If others are already waiting, space or not, we have to get in line. + m->SortReceiveThreads(); + if (m->receiveWaitingThreads.empty()) { - Memory::Memcpy(receiveBufAddr, Memory::GetPointer(m->buffer), receiveSize); - m->nmp.freeSize += receiveSize; - memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + receiveSize, m->nmp.bufSize - m->nmp.freeSize); - curReceiveAddr = receiveBufAddr + receiveSize; - receiveSize = 0; + if (receiveSize <= m->GetUsedSize()) + bytesToReceive = receiveSize; + else if (waitMode == SCE_KERNEL_MPW_ASAP) + bytesToReceive = m->GetUsedSize(); } - // Else, if mode is ASAP and there's at list 1 available byte of data: copy all the available data - else if (waitMode == SCE_KERNEL_MPW_ASAP && m->nmp.freeSize != m->nmp.bufSize) + + if (bytesToReceive != 0) { - Memory::Memcpy(receiveBufAddr, Memory::GetPointer(m->buffer), m->nmp.bufSize - m->nmp.freeSize); - receiveSize -= m->nmp.bufSize - m->nmp.freeSize; - curReceiveAddr = receiveBufAddr + m->nmp.bufSize - m->nmp.freeSize; - m->nmp.freeSize = m->nmp.bufSize; + Memory::Memcpy(curReceiveAddr, Memory::GetPointer(m->buffer), bytesToReceive); + m->nmp.freeSize += bytesToReceive; + memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize()); + curReceiveAddr += bytesToReceive; + receiveSize -= bytesToReceive; + + if (m->CheckSendThreads()) + hleReSchedule(cbEnabled, "msgpipe data received"); } - else + else if (receiveSize != 0) { if (poll) return SCE_KERNEL_ERROR_MPP_EMPTY; @@ -710,11 +701,6 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int return 0; } } - - if (curReceiveAddr != receiveBufAddr) - { - m->CheckSendThreads(); - } } if (Memory::IsValidAddress(resultAddr)) From 642e7b255e2964d868eb033e497d6edb389df4b3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 17:13:05 -0700 Subject: [PATCH 22/26] Drain as much as possible before waiting. --- Core/HLE/sceKernelMsgPipe.cpp | 52 ++++++++++++++++------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index be5133dde3..d444384f76 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -170,19 +170,18 @@ struct MsgPipe : public KernelObject while (!sendWaitingThreads.empty() && nmp.freeSize > 0) { MsgPipeWaitingThread *thread = &sendWaitingThreads.front(); - u32 bytesToSend = 0; - if (thread->bufSize <= (u32) nmp.freeSize) - bytesToSend = thread->bufSize; - else if (thread->waitMode == SCE_KERNEL_MPW_ASAP && nmp.freeSize != 0) - bytesToSend = nmp.freeSize; + u32 bytesToSend = std::min(thread->freeSize, (u32) nmp.freeSize); - if (bytesToSend != 0) + thread->ReadBuffer(Memory::GetPointer(buffer + GetUsedSize()), bytesToSend); + nmp.freeSize -= bytesToSend; + filledSpace = true; + + if (thread->waitMode == SCE_KERNEL_MPW_ASAP || thread->freeSize == 0) { - thread->ReadBuffer(Memory::GetPointer(buffer + GetUsedSize()), bytesToSend); thread->Complete(GetUID(), 0); sendWaitingThreads.erase(sendWaitingThreads.begin()); wokeThreads = true; - filledSpace = true; + thread = NULL; } // Unlike receives, we don't do partial sends. Stop at first blocked thread. else @@ -216,7 +215,7 @@ struct MsgPipe : public KernelObject if (thread->waitMode == SCE_KERNEL_MPW_ASAP || thread->freeSize == 0) { - thread->Complete(GetUID(), 0, thread->bufSize); + thread->Complete(GetUID(), 0); receiveWaitingThreads.erase(receiveWaitingThreads.begin()); wokeThreads = true; thread = NULL; @@ -665,29 +664,24 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int return SCE_KERNEL_ERROR_ILLEGAL_SIZE; } - u32 bytesToReceive = 0; - // If others are already waiting, space or not, we have to get in line. - m->SortReceiveThreads(); - if (m->receiveWaitingThreads.empty()) + while (m->GetUsedSize() > 0) { - if (receiveSize <= m->GetUsedSize()) - bytesToReceive = receiveSize; - else if (waitMode == SCE_KERNEL_MPW_ASAP) - bytesToReceive = m->GetUsedSize(); + u32 bytesToReceive = std::min(receiveSize, m->GetUsedSize()); + if (bytesToReceive != 0) + { + Memory::Memcpy(curReceiveAddr, Memory::GetPointer(m->buffer), bytesToReceive); + m->nmp.freeSize += bytesToReceive; + memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize()); + curReceiveAddr += bytesToReceive; + receiveSize -= bytesToReceive; + + m->CheckSendThreads(); + } + else + break; } - if (bytesToReceive != 0) - { - Memory::Memcpy(curReceiveAddr, Memory::GetPointer(m->buffer), bytesToReceive); - m->nmp.freeSize += bytesToReceive; - memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize()); - curReceiveAddr += bytesToReceive; - receiveSize -= bytesToReceive; - - if (m->CheckSendThreads()) - hleReSchedule(cbEnabled, "msgpipe data received"); - } - else if (receiveSize != 0) + if (receiveSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curReceiveAddr == receiveBufAddr)) { if (poll) return SCE_KERNEL_ERROR_MPP_EMPTY; From 2d1b2bc7699e08e360e06a3be6301900fdb80f74 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 17:14:13 -0700 Subject: [PATCH 23/26] Writing 0s on delete/cancel wasn't right after all. --- Core/HLE/sceKernelMsgPipe.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index d444384f76..b160898872 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -82,20 +82,18 @@ struct MsgPipeWaitingThread } } - void Complete(SceUID waitID, int result, u32 transferred = (u32)-1) const + void Complete(SceUID waitID, int result) const { if (IsStillWaiting(waitID)) { WriteCurrentTimeout(waitID); - if (transferred != (u32)-1 && transferredBytes.IsValid()) - *transferredBytes = transferred; __KernelResumeThreadFromWait(id, result); } } void Cancel(SceUID waitID, int result) const { - Complete(waitID, result, 0); + Complete(waitID, result); } void ReadBuffer(u8 *dest, u32 len) From a53c5d291c9a589d0a94f059cccf73d722f3cc11 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 17:20:52 -0700 Subject: [PATCH 24/26] Update result on non-buffer receive empty too. --- Core/HLE/sceKernelMsgPipe.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index b160898872..93fe38281e 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -477,7 +477,7 @@ int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, { if (poll) { - // Generally, result is not set to 0 in this case. But for a 0 size buffer in ASAP mode, it is. + // Generally, result is not updated in this case. But for a 0 size buffer in ASAP mode, it is. if (Memory::IsValidAddress(resultAddr) && waitMode == SCE_KERNEL_MPW_ASAP) Memory::Write_U32(curSendAddr - sendBufAddr, resultAddr); return SCE_KERNEL_ERROR_MPP_FULL; @@ -641,7 +641,12 @@ int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int if (receiveSize != 0 && (waitMode != SCE_KERNEL_MPW_ASAP || curReceiveAddr == receiveBufAddr)) { if (poll) + { + // Generally, result is not updated in this case. But for a 0 size buffer in ASAP mode, it is. + if (Memory::IsValidAddress(resultAddr) && waitMode == SCE_KERNEL_MPW_ASAP) + Memory::Write_U32(curReceiveAddr - receiveBufAddr, resultAddr); return SCE_KERNEL_ERROR_MPP_EMPTY; + } else { m->AddReceiveWaitingThread(__KernelGetCurThread(), curReceiveAddr, receiveSize, waitMode, resultAddr); From 4f7f963274dd8f162189da242179c78d51b9b7b3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 17:31:17 -0700 Subject: [PATCH 25/26] Correct sceKernelReferMsgPipeStatus(). --- Core/HLE/sceKernel.cpp | 2 +- Core/HLE/sceKernelMsgPipe.cpp | 26 ++++++++++++++++++-------- Core/HLE/sceKernelMsgPipe.h | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index a729fa6a76..7f56ca6b32 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -766,7 +766,7 @@ const HLEFunction ThreadManForUser[] = {0xFBFA697D,WrapI_IUUUUU, "sceKernelReceiveMsgPipeCB"}, {0xDF52098F,WrapI_IUUUU, "sceKernelTryReceiveMsgPipe"}, {0x349B864D,WrapI_IUU, "sceKernelCancelMsgPipe"}, - {0x33BE4024,sceKernelReferMsgPipeStatus,"sceKernelReferMsgPipeStatus"}, + {0x33BE4024,WrapI_IU, "sceKernelReferMsgPipeStatus"}, {0x56C039B5,WrapI_CIUUU,"sceKernelCreateVpl"}, {0x89B3D48C,WrapI_I,"sceKernelDeleteVpl"}, diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 93fe38281e..b07e17f6f8 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -776,23 +776,33 @@ int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThr return 0; } -void sceKernelReferMsgPipeStatus() +int sceKernelReferMsgPipeStatus(SceUID uid, u32 statusPtr) { - SceUID uid = PARAM(0); - u32 msgPipeStatusAddr = PARAM(1); - - DEBUG_LOG(HLE,"sceKernelReferMsgPipeStatus(%i, %08x)", uid, msgPipeStatusAddr); u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (m) { + if (!Memory::IsValidAddress(statusPtr)) + { + ERROR_LOG(HLE, "sceKernelReferMsgPipeStatus(%i, %08x): invalid address", uid, statusPtr); + return -1; + } + + DEBUG_LOG(HLE, "sceKernelReferMsgPipeStatus(%i, %08x)", uid, statusPtr); + + // Clean up any that have timed out. + m->SortReceiveThreads(); + m->SortSendThreads(); + m->nmp.numSendWaitThreads = (int) m->sendWaitingThreads.size(); m->nmp.numReceiveWaitThreads = (int) m->receiveWaitingThreads.size(); - Memory::WriteStruct(msgPipeStatusAddr, &m->nmp); - RETURN(0); + if (Memory::Read_U32(statusPtr) != 0) + Memory::WriteStruct(statusPtr, &m->nmp); + return 0; } else { - RETURN(error); + DEBUG_LOG(HLE, "sceKernelReferMsgPipeStatus(%i, %08x): bad message pipe", uid, statusPtr); + return error; } } diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index b80df69467..28bd6e812c 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -28,7 +28,7 @@ int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr); int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr); int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr); -void sceKernelReferMsgPipeStatus(); +int sceKernelReferMsgPipeStatus(SceUID uid, u32 statusPtr); void __KernelMsgPipeInit(); void __KernelMsgPipeDoState(PointerWrap &p); From 15cf413fec31754214ba6bcc731ed06f99b4bd71 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Aug 2013 19:04:21 -0700 Subject: [PATCH 26/26] Update tests. --- pspautotests | 2 +- test.py | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/pspautotests b/pspautotests index 8b0c30efe5..f003246b8d 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 8b0c30efe52e0c799a99a632e5e743a56375d3ec +Subproject commit f003246b8d8803d9bdb7d0e3de53cab620eda8b9 diff --git a/test.py b/test.py index b6afa2343f..1de45a91e2 100755 --- a/test.py +++ b/test.py @@ -68,6 +68,7 @@ tests_good = [ "cpu/lsu/lsu", "cpu/fpu/fpu", + "audio/atrac/ids", "ctrl/ctrl", "ctrl/idle/idle", "ctrl/sampling/sampling", @@ -86,6 +87,7 @@ tests_good = [ "misc/dcache", "mstick/mstick", "string/string", + "sysmem/freesize", "gpu/callbacks/ge_callbacks", "threads/alarm/alarm", "threads/alarm/cancel/cancel", @@ -119,6 +121,16 @@ tests_good = [ "threads/mbx/receive/receive", "threads/mbx/refer/refer", "threads/mbx/send/send", + "threads/msgpipe/msgpipe", + "threads/msgpipe/cancel", + "threads/msgpipe/create", + "threads/msgpipe/data", + "threads/msgpipe/delete", + "threads/msgpipe/receive", + "threads/msgpipe/refer", + "threads/msgpipe/send", + "threads/msgpipe/tryreceive", + "threads/msgpipe/trysend", "threads/mutex/create", "threads/mutex/delete", "threads/mutex/lock", @@ -139,6 +151,7 @@ tests_good = [ "threads/threads/extend", "threads/threads/release", "threads/threads/rotate", + "threads/threads/suspend", "threads/threads/threadend", "threads/threads/threads", "threads/wakeup/wakeup", @@ -149,6 +162,7 @@ tests_good = [ "threads/vpl/refer", "threads/vpl/try", "threads/vpl/vpl", + "utility/savedata/filelist", "utility/systemparam/systemparam", "power/power", "umd/callbacks/umd", @@ -161,8 +175,10 @@ tests_next = [ "audio/atrac/atractest", "audio/mp3/mp3test", "audio/sascore/sascore", + "audot/sceaudio/datalen", + "audot/sceaudio/output", + "audot/sceaudio/reserve", "threads/fpl/fpl", - "threads/msgpipe/msgpipe", "threads/mutex/cancel", "threads/scheduling/dispatch", "threads/scheduling/scheduling", @@ -170,9 +186,15 @@ tests_next = [ "threads/threads/create", "threads/threads/refer", "threads/threads/start", + "threads/threads/terminate", "threads/vtimers/vtimer", "threads/vpl/allocate", "threads/vpl/create", + "utility/savedata/autosave", + "utility/savedata/getsize", + "utility/savedata/idlist", + "utility/savedata/makedata", + "utility/savedata/sizes", "gpu/commands/basic", "gpu/commands/material", "gpu/complex/complex", @@ -185,6 +207,7 @@ tests_next = [ "gpu/triangle/triangle", "font/fonttest", "io/file/file", + "io/file/rename", "io/io/io", "io/iodrv/iodrv", "modules/loadexec/loader", @@ -193,8 +216,10 @@ tests_next = [ "sysmem/sysmem", "umd/io/umd_io", "umd/raw_access/raw_access", + "video/mpeg/basic", "video/pmf/pmf", "video/pmf_simple/pmf_simple", + "video/psmfplayer/basic", ] # These don't even run (or run correctly) on the real PSP