diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index abbab99c02..0676c8f828 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -296,9 +296,9 @@ const Executable *RecompilationEngine::GetExecutable(u32 address, bool isFunctio return isFunction ? &executeFunc : &executeUntilReturn; } -std::mutex* RecompilationEngine::GetMutexForAddress(u32 address) { +std::pair >* RecompilationEngine::GetMutexAndCounterForAddress(u32 address) { std::lock_guard lock(m_address_locks_lock); - std::unordered_map::iterator It = m_address_locks.find(address); + std::unordered_map> >::iterator It = m_address_locks.find(address); if (It == m_address_locks.end()) return nullptr; return &(It->second); @@ -549,14 +549,23 @@ void RecompilationEngine::CompileBlock(BlockEntry & block_entry) { std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = nullptr; } - std::unordered_map::iterator It2 = m_address_locks.find(block_entry.cfg.start_address); + std::unordered_map> >::iterator It2 = m_address_locks.find(block_entry.cfg.start_address); if (It2 == m_address_locks.end()) { std::lock_guard lock(m_address_locks_lock); (void)m_address_locks[block_entry.cfg.start_address]; + m_address_locks[block_entry.cfg.start_address].second.store(0); } - std::lock_guard lock(m_address_locks[block_entry.cfg.start_address]); + std::lock_guard lock(m_address_locks[block_entry.cfg.start_address].first); + + int loopiteration = 0; + while (m_address_locks[block_entry.cfg.start_address].second.load() > 0) + { + std::this_thread::yield(); + if (loopiteration++ > 10000000) + return; + } std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = std::unique_ptr(compileResult.second); std::get<0>(m_address_to_function[block_entry.cfg.start_address]) = compileResult.first; @@ -706,13 +715,17 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledFunction, context >> 32, context & 0xFFFFFFFF); while (PollStatus(ppu_state) == false) { - std::mutex *mut = execution_engine->m_recompilation_engine->GetMutexForAddress(ppu_state->PC); + std::pair> *mut = execution_engine->m_recompilation_engine->GetMutexAndCounterForAddress(ppu_state->PC); if (mut) { - std::lock_guard lock(*mut); + { + std::lock_guard lock(mut->first); + mut->second.fetch_add(1); + } const Executable *executable = execution_engine->m_recompilation_engine->GetCompiledExecutableIfAvailable(ppu_state->PC); auto entry = ppu_state->PC; u32 exit = (u32)(*executable)(ppu_state, 0); execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledBlock, entry, exit); + mut->second.fetch_sub(1); if (exit == 0) return 0; } else { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.h b/rpcs3/Emu/Cell/PPULLVMRecompiler.h index 36495acc21..4a24a7e97c 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.h +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.h @@ -1012,7 +1012,7 @@ namespace ppu_recompiler_llvm { /** * Get a mutex for an address. Used to avoid modifying a block currently in execution. **/ - std::mutex* GetMutexForAddress(u32 address); + std::pair >* GetMutexAndCounterForAddress(u32 address); /** * Get the executable for the specified address if a compiled version is @@ -1107,7 +1107,7 @@ namespace ppu_recompiler_llvm { typedef std::tuple, u32> ExecutableStorage; /// Address to ordinal cahce. Key is address. std::unordered_map m_address_to_function; - std::unordered_map m_address_locks; + std::unordered_map > > m_address_locks; /// The time at which the m_address_to_ordinal cache was last cleared std::chrono::high_resolution_clock::time_point m_last_cache_clear_time;