mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-07-09 17:25:18 -06:00
PPU LLVM: Recycle current thread for exxecution
Prevent invoking more than utils::get_max_threads() active thrreads at a time. Windows sees more than utils::get_max_threads() active threads as potentially malicious behavior and lowers the program's overall CPU time.
This commit is contained in:
parent
f05ece47ce
commit
24a1576629
@ -4641,9 +4641,6 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
// Info to load to main JIT instance (true - compiled)
|
// Info to load to main JIT instance (true - compiled)
|
||||||
std::vector<std::pair<std::string, bool>> link_workload;
|
std::vector<std::pair<std::string, bool>> link_workload;
|
||||||
|
|
||||||
// Sync variable to acquire workloads
|
|
||||||
atomic_t<u32> work_cv = 0;
|
|
||||||
|
|
||||||
bool compiled_new = false;
|
bool compiled_new = false;
|
||||||
|
|
||||||
bool has_mfvscr = false;
|
bool has_mfvscr = false;
|
||||||
@ -5250,12 +5247,16 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
// Create worker threads for compilation
|
// Create worker threads for compilation
|
||||||
if (!workload.empty())
|
if (!workload.empty())
|
||||||
{
|
{
|
||||||
|
// Sync variable to acquire workloads
|
||||||
|
atomic_t<u64> work_cv = 0;
|
||||||
|
atomic_t<u64> work_done = 0;
|
||||||
|
|
||||||
// Update progress dialog
|
// Update progress dialog
|
||||||
g_progr_ptotal += ::size32(workload);
|
g_progr_ptotal += ::size32(workload);
|
||||||
|
|
||||||
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_COMPILING_PPU_MODULES);
|
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_COMPILING_PPU_MODULES);
|
||||||
|
|
||||||
const u32 thread_count = std::min(::size32(workload), rpcs3::utils::get_max_threads());
|
const u32 thread_count = std::max<u32>(std::min<u32>(::size32(workload), rpcs3::utils::get_max_threads()), 1) - 1;
|
||||||
|
|
||||||
struct thread_index_allocator
|
struct thread_index_allocator
|
||||||
{
|
{
|
||||||
@ -5264,7 +5265,8 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
|
|
||||||
struct thread_op
|
struct thread_op
|
||||||
{
|
{
|
||||||
atomic_t<u32>& work_cv;
|
const std::add_pointer_t<atomic_t<u64>> work_cv;
|
||||||
|
const std::add_pointer_t<atomic_t<u64>> work_done;
|
||||||
std::vector<std::pair<std::string, ppu_module<lv2_obj>>>& workload;
|
std::vector<std::pair<std::string, ppu_module<lv2_obj>>>& workload;
|
||||||
const ppu_module<lv2_obj>& main_module;
|
const ppu_module<lv2_obj>& main_module;
|
||||||
const std::string& cache_path;
|
const std::string& cache_path;
|
||||||
@ -5272,10 +5274,11 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
|
|
||||||
std::unique_lock<decltype(jit_core_allocator::sem)> core_lock;
|
std::unique_lock<decltype(jit_core_allocator::sem)> core_lock;
|
||||||
|
|
||||||
thread_op(atomic_t<u32>& work_cv, std::vector<std::pair<std::string, ppu_module<lv2_obj>>>& workload
|
thread_op(atomic_t<u64>* _work_cv, atomic_t<u64>* _work_done, std::vector<std::pair<std::string, ppu_module<lv2_obj>>>& workload
|
||||||
, const cpu_thread* cpu, const ppu_module<lv2_obj>& main_module, const std::string& cache_path, decltype(jit_core_allocator::sem)& sem) noexcept
|
, const cpu_thread* cpu, const ppu_module<lv2_obj>& main_module, const std::string& cache_path, decltype(jit_core_allocator::sem)& sem) noexcept
|
||||||
|
|
||||||
: work_cv(work_cv)
|
: work_cv(_work_cv)
|
||||||
|
, work_done(_work_done)
|
||||||
, workload(workload)
|
, workload(workload)
|
||||||
, main_module(main_module)
|
, main_module(main_module)
|
||||||
, cache_path(cache_path)
|
, cache_path(cache_path)
|
||||||
@ -5287,6 +5290,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
|
|
||||||
thread_op(const thread_op& other) noexcept
|
thread_op(const thread_op& other) noexcept
|
||||||
: work_cv(other.work_cv)
|
: work_cv(other.work_cv)
|
||||||
|
, work_done(other.work_done)
|
||||||
, workload(other.workload)
|
, workload(other.workload)
|
||||||
, main_module(other.main_module)
|
, main_module(other.main_module)
|
||||||
, cache_path(other.cache_path)
|
, cache_path(other.cache_path)
|
||||||
@ -5309,7 +5313,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
pthread_jit_write_protect_np(false);
|
pthread_jit_write_protect_np(false);
|
||||||
#endif
|
#endif
|
||||||
for (u32 i = work_cv++; i < workload.size(); i = work_cv++, g_progr_pdone++)
|
for (u32 i = (*work_cv)++; i < workload.size(); i = (*work_cv)++, (*work_done)++, g_progr_pdone++)
|
||||||
{
|
{
|
||||||
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
||||||
{
|
{
|
||||||
@ -5331,17 +5335,20 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
core_lock.unlock();
|
core_lock.unlock();
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
pthread_jit_write_protect_np(true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prevent watchdog thread from terminating
|
// Prevent watchdog thread from terminating
|
||||||
g_watchdog_hold_ctr++;
|
g_watchdog_hold_ctr++;
|
||||||
|
|
||||||
named_thread_group threads(fmt::format("PPUW.%u.", ++g_fxo->get<thread_index_allocator>().index), thread_count
|
const std::string worker_group_name = fmt::format("PPUW.%u.", ++g_fxo->get<thread_index_allocator>().index);
|
||||||
, thread_op(work_cv, workload, cpu, info, cache_path, g_fxo->get<jit_core_allocator>().sem)
|
const auto try_lock_thread = [&](u32 thread_index, thread_op& op)
|
||||||
, [&](u32 /*thread_index*/, thread_op& op)
|
|
||||||
{
|
{
|
||||||
const bool to_lock = work_cv < workload.size() && (cpu ? !cpu->state.all_of(cpu_flag::exit) : !Emu.IsStopped());
|
const bool to_lock = (thread_index + *op.work_done) < workload.size() && (cpu ? !cpu->state.all_of(cpu_flag::exit) : !Emu.IsStopped());
|
||||||
|
|
||||||
if (!to_lock)
|
if (!to_lock)
|
||||||
{
|
{
|
||||||
@ -5352,7 +5359,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
op.core_lock.lock();
|
op.core_lock.lock();
|
||||||
|
|
||||||
// Second check before creating another thread
|
// Second check before creating another thread
|
||||||
const bool to_unlock = !(work_cv < workload.size() && (cpu ? !cpu->state.all_of(cpu_flag::exit) : !Emu.IsStopped()));
|
const bool to_unlock = !((thread_index + *op.work_done) < workload.size() && (cpu ? !cpu->state.all_of(cpu_flag::exit) : !Emu.IsStopped()));
|
||||||
|
|
||||||
if (to_unlock)
|
if (to_unlock)
|
||||||
{
|
{
|
||||||
@ -5361,10 +5368,26 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
};
|
||||||
|
|
||||||
|
named_thread_group threads(worker_group_name, thread_count
|
||||||
|
, thread_op(&work_cv, &work_done, workload, cpu, info, cache_path, g_fxo->get<jit_core_allocator>().sem)
|
||||||
|
, try_lock_thread);
|
||||||
|
|
||||||
|
const auto old_name = thread_ctrl::get_name();
|
||||||
|
thread_ctrl::set_name(worker_group_name + std::to_string(thread_count + 1));
|
||||||
|
|
||||||
|
thread_op cur_op(&work_cv, &work_done, workload, cpu, info, cache_path, g_fxo->get<jit_core_allocator>().sem);
|
||||||
|
|
||||||
|
if (try_lock_thread(thread_count, cur_op))
|
||||||
|
{
|
||||||
|
// Recycle current thread: reduce overall thrread count
|
||||||
|
cur_op();
|
||||||
|
}
|
||||||
|
|
||||||
threads.join();
|
threads.join();
|
||||||
|
|
||||||
|
thread_ctrl::set_name(old_name);
|
||||||
g_watchdog_hold_ctr--;
|
g_watchdog_hold_ctr--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user