diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 4d8ece34af..37c5810705 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -86,7 +86,10 @@ bool CPUThread::IsPaused() const void CPUThread::DumpInformation() const { - LOG_WARNING(GENERAL, RegsToString()); + if (!Emu.IsStopped()) + { + LOG_NOTICE(GENERAL, RegsToString()); + } } void CPUThread::Run() diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 1701c951f3..ca58e30060 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -219,6 +219,9 @@ namespace vm { return false; } + + // clear predicate + pred = nullptr; } catch (...) { @@ -233,16 +236,13 @@ namespace vm // dummy return value return true; }; - - // signal unconditionally (may be already signaled) - thread->Signal(); - - return true; } - // clear predicate and signal - pred = nullptr; + // set addr and mask to invalid values to prevent further polling + addr = 0; + mask = ~0; + // signal thread (must not be signaled yet) if (!thread->Signal()) { throw EXCEPTION("Thread already signaled"); @@ -271,10 +271,10 @@ namespace vm m_waiter->thread->cv.wait(m_lock); } - // if another thread called pred(), it must be removed + // if another thread successfully called pred(), it must be set to null if (m_waiter->pred) { - // pred() should rethrow exception caught by another thread + // if pred() called by another thread threw an exception, rethrow it m_waiter->pred(); throw EXCEPTION("Unexpected"); @@ -283,7 +283,9 @@ namespace vm waiter_lock_t::~waiter_lock_t() { - // remove predicate to avoid excessive signaling + // reset some data to avoid excessive signaling + m_waiter->addr = 0; + m_waiter->mask = ~0; m_waiter->pred = nullptr; // unlock thread's mutex to avoid deadlock with g_waiter_list_mutex @@ -302,7 +304,8 @@ namespace vm { waiter_t& waiter = g_waiter_list[i]; - if (((waiter.addr ^ addr) & (mask & waiter.mask)) == 0 && waiter.thread && waiter.pred) + // check address range overlapping using masks generated from size (power of 2) + if (waiter.thread && ((waiter.addr ^ addr) & (mask & waiter.mask)) == 0) { waiter.try_notify(); } @@ -323,24 +326,28 @@ namespace vm bool notify_all() { - std::unique_lock lock(g_waiter_list_mutex, std::try_to_lock); + std::unique_lock lock(g_waiter_list_mutex); - if (lock) + std::size_t waiters = 0; + std::size_t signaled = 0; + + for (std::size_t i = 0; i < g_waiter_max; i++) { - for (std::size_t i = 0; i < g_waiter_max; i++) - { - waiter_t& waiter = g_waiter_list[i]; + waiter_t& waiter = g_waiter_list[i]; - if (waiter.thread && waiter.pred) + if (waiter.thread && waiter.addr) + { + waiters++; + + if (waiter.try_notify()) { - waiter.try_notify(); + signaled++; } } - - return true; } - return false; + // return true if waiter list is empty or all available waiters were signaled + return waiters == signaled; } void start() diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 60b9121b83..a39e76b00f 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -37,7 +37,7 @@ namespace vm struct waiter_t { u32 addr = 0; - u32 mask = 0; + u32 mask = ~0; CPUThread* thread = nullptr; std::function pred; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 474e400e99..5c0ebe5fac 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -57,7 +57,6 @@ never_inline s32 savedata_op( if (!lock) { - cellSysutil.Error("savedata_op(): failed to lock the mutex."); return CELL_SAVEDATA_ERROR_BUSY; } @@ -192,7 +191,6 @@ never_inline s32 savedata_op( if (result->result < 0) { - cellSysutil.Error("savedata_op(): funcList returned result < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -304,7 +302,6 @@ never_inline s32 savedata_op( if (result->result < 0) { - cellSysutil.Error("savedata_op(): funcFixed returned result < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -346,31 +343,10 @@ never_inline s32 savedata_op( PSFLoader psf; - // Create save directory if necessary - if (save_entry.isNew) - { - if (!Emu.GetVFS().ExistsDir(dir_path) && !Emu.GetVFS().CreateDir(dir_path)) - { - cellSysutil.Error("savedata_op(): Savedata directory creation failed."); - } - else - { - // Is loading the PARAM.SFO really necessary? Setting empty stuff seems to fix a couple games. - psf.SetInteger("ATTRIBUTE", 0); - psf.SetString("TITLE", ""); - psf.SetString("SUB_TITLE", ""); - psf.SetString("DETAIL", ""); - psf.SetString("SAVEDATA_LIST_PARAM", ""); - } - } - // Load PARAM.SFO { - if (!save_entry.isNew) - { - vfsFile f(sfo_path); - psf.Load(f); - } + vfsFile f(sfo_path); + psf.Load(f); } // Get save stats @@ -460,7 +436,6 @@ never_inline s32 savedata_op( if (result->result < 0) { - cellSysutil.Error("savedata_op(): funcStat returned result < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -510,6 +485,12 @@ never_inline s32 savedata_op( } } + // Create save directory if necessary + if (psf && save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path)) + { + // Let's ignore this error for now + } + // Enter the loop where the save files are read/created/deleted vm::stackvar fileGet(CPU); vm::stackvar fileSet(CPU); @@ -523,7 +504,6 @@ never_inline s32 savedata_op( if (result->result < 0) { - cellSysutil.Error("savedata_op(): funcFile returned result < 0."); return CELL_SAVEDATA_ERROR_CBRESULT; } @@ -772,7 +752,7 @@ s32 cellSaveDataListAutoLoad( } s32 cellSaveDataDelete2(u32 container) -{ +{ cellSysutil.Todo("cellSaveDataDelete2(container=0x%x)", container); return CELL_SAVEDATA_RET_CANCEL; diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index ac7690d807..a1f21d76e7 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -71,7 +71,7 @@ namespace ppu_func_detail static force_inline T get_arg(PPUThread& CPU) { // TODO: check stack argument displacement - const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); + const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); return cast_from_ppu_gpr(res); } };