From f05ece47ce67ecb48cb79cb3d244e7cc7c6eb7c9 Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Thu, 21 May 2026 21:59:14 +0300 Subject: [PATCH] PPU LLVM: Fix concurrrency weakness of jit_module_manager --- rpcs3/Emu/Cell/PPUThread.cpp | 41 ++++++++++++++++++++---------------- rpcs3/util/fnv_hash.hpp | 12 +++++++++++ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 6f4b9dafb9..d3f31df73d 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -64,6 +64,7 @@ #include "util/v128.hpp" #include "util/simd.hpp" #include "util/sysinfo.hpp" +#include "util/fnv_hash.hpp" #include "Utilities/sema.h" @@ -3472,9 +3473,6 @@ struct jit_core_allocator // Initialize global semaphore with the max number of threads ::semaphore<0x7fff> sem{std::max(thread_count, 1)}; - // Mutex for special extra-large modules to compile alone - shared_mutex shared_mtx; - static s16 limit() { return static_cast(std::min(0x7fff, utils::get_thread_count())); @@ -3500,11 +3498,28 @@ namespace std::unordered_map map; }; - std::array buckets; + std::array buckets; bucket_t& get_bucket(std::string_view sv) { - return buckets[std::hash()(sv) % std::size(buckets)]; + const std::string& cache_path = fs::get_cache_dir(); + + if (sv.starts_with(cache_path)) + { + sv = sv.substr(cache_path.size()); + } + + const usz hash = rpcs3::hash_array(sv.data(), sv.size()); + + usz final_index = 0; + + for (usz i = 0; i < sizeof(hash); i++) + { + final_index ^= (hash >> (i * 8)) % 256; + } + + final_index ^= sv.size(); + return buckets[final_index % std::size(buckets)]; } jit_module& get(const std::string& name) @@ -4127,9 +4142,12 @@ extern void ppu_precompile(std::vector& dir_queue, std::vectorget().sem); + if (auto prx = ppu_load_prx(obj, true, path, offset)) { obj.clear(), src.close(); // Clear decrypted file and elf object memory + //.unlock(); ppu_initialize(*prx, false, file_size); ppu_finalize(*prx, true); continue; @@ -5301,19 +5319,6 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s // Keep allocating workload const auto& [obj_name, part] = std::as_const(workload)[i]; - std::shared_lock rlock(g_fxo->get().shared_mtx, std::defer_lock); - std::unique_lock lock(g_fxo->get().shared_mtx, std::defer_lock); - - if (false && part.jit_bounds && part.parent->funcs.size() >= 0x8000) - { - // Make a large symbol-resolving function compile alone because it has massive memory requirements - lock.lock(); - } - else - { - rlock.lock(); - } - ppu_log.warning("LLVM: Compiling module %s%s", cache_path, obj_name); { diff --git a/rpcs3/util/fnv_hash.hpp b/rpcs3/util/fnv_hash.hpp index 1da02d02a5..09cf94918a 100644 --- a/rpcs3/util/fnv_hash.hpp +++ b/rpcs3/util/fnv_hash.hpp @@ -87,4 +87,16 @@ namespace rpcs3 } return hash; } + + template + requires std::is_integral_v + static inline usz hash_array(const T* arr, size_t count) + { + usz hash = fnv_seed; + for (size_t i = 0; i < count; ++i) + { + hash = hash64(hash, arr[i]); + } + return hash; + } }