From 7698064f5a937f140f7e5d05407f87b9bb77a763 Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 6 Sep 2022 14:56:47 +0300 Subject: [PATCH] SPU: Untangle VM lock to avoid deadlocks --- rpcs3/Emu/Cell/RawSPUThread.cpp | 4 ++++ rpcs3/Emu/Cell/SPUThread.cpp | 16 +++------------- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 11 +++++++++-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 5dc749041b..09c838a380 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -323,6 +323,8 @@ void spu_load_exec(const spu_exec_object& elf) spu_thread::g_raw_spu_ctr++; auto spu = idm::make_ptr>(nullptr, 0, "test_spu", 0); + ensure(vm::get(vm::spu)->falloc(spu->vm_offset(), SPU_LS_SIZE, &spu->shm, vm::page_size_64k)); + spu->map_ls(*spu->shm, spu->ls); for (const auto& prog : elf.progs) { @@ -343,6 +345,8 @@ void spu_load_rel_exec(const spu_rel_object& elf) spu_thread::g_raw_spu_ctr++; auto spu = idm::make_ptr>(nullptr, 0, "test_spu", 0); + ensure(vm::get(vm::spu)->falloc(spu->vm_offset(), SPU_LS_SIZE, &spu->shm, vm::page_size_64k)); + spu->map_ls(*spu->shm, spu->ls); u64 total_memsize = 0; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 46a029d33f..28efdfe1cf 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1656,11 +1656,11 @@ spu_thread::~spu_thread() perf_log.notice("Perf stats for PUTLLC reload: successs %u, failure %u", last_succ, last_fail); } -u8* spu_thread::map_ls(utils::shm& shm) +u8* spu_thread::map_ls(utils::shm& shm, void* ptr) { vm::writer_lock mlock; - const auto ls = static_cast(ensure(utils::memory_reserve(SPU_LS_SIZE * 5, nullptr, true))) + SPU_LS_SIZE * 2; + const auto ls = ptr ? static_cast(ptr) : static_cast(ensure(utils::memory_reserve(SPU_LS_SIZE * 5, nullptr, true))) + SPU_LS_SIZE * 2; ensure(shm.map_critical(ls - SPU_LS_SIZE).first && shm.map_critical(ls).first && shm.map_critical(ls + SPU_LS_SIZE).first); return ls; } @@ -1671,7 +1671,7 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u , index(index) , thread_type(group ? spu_type::threaded : is_isolated ? spu_type::isolated : spu_type::raw) , shm(std::make_shared(SPU_LS_SIZE)) - , ls(map_ls(*this->shm)) + , ls(static_cast(utils::memory_reserve(SPU_LS_SIZE * 5, nullptr, true)) + SPU_LS_SIZE * 2) , option(option) , lv2_id(lv2_id) , spu_tname(make_single(name)) @@ -1696,16 +1696,6 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u utils::memory_commit(vm::g_stat_addr + vm_offset(), SPU_LS_SIZE); } - if (!group) - { - ensure(vm::get(vm::spu)->falloc(vm_offset(), SPU_LS_SIZE, &shm, vm::page_size_64k)); - } - else - { - // alloc_hidden indicates falloc to allocate page with no access rights in base memory - ensure(vm::get(vm::spu)->falloc(vm_offset(), SPU_LS_SIZE, &shm, static_cast(vm::page_size_64k) | static_cast(vm::alloc_hidden))); - } - if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit || g_cfg.core.spu_decoder == spu_decoder_type::llvm) { if (g_cfg.core.spu_block_size != spu_block_size_type::safe) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index e478415baa..eb351338c7 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -918,7 +918,7 @@ public: return group ? SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (id & 0xffffff) : RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index; } - static u8* map_ls(utils::shm& shm); + static u8* map_ls(utils::shm& shm, void* ptr = nullptr); // Returns true if reservation existed but was just discovered to be lost // It is safe to use on any address, even if not directly accessed by SPU (so it's slower) diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index fe49e647db..c7f481b566 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -707,6 +707,11 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g return spu; })); + // alloc_hidden indicates falloc to allocate page with no access rights in base memory + auto& spu = group->threads[inited]; + ensure(vm::get(vm::spu)->falloc(spu->vm_offset(), SPU_LS_SIZE, &spu->shm, static_cast(vm::page_size_64k) | static_cast(vm::alloc_hidden))); + spu->map_ls(*spu->shm, spu->ls); + *thread = tid; group->args[inited] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; @@ -2206,9 +2211,11 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr at index = 0; } - const u32 tid = idm::make>(nullptr, index, "", index); + const auto spu = idm::make_ptr>(nullptr, index, "", index); + ensure(vm::get(vm::spu)->falloc(spu->vm_offset(), SPU_LS_SIZE, &spu->shm, vm::page_size_64k)); + spu->map_ls(*spu->shm, spu->ls); - spu_thread::g_raw_spu_id[index] = (ensure(tid)); + spu_thread::g_raw_spu_id[index] = idm::last_id(); *id = index;