From 00895862e10bbbcc39b75380904a112e2496a661 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 17 Oct 2019 19:24:34 +0300 Subject: [PATCH] Fix sys_vm_t destructor It's not a destructor's job to free vm like this. --- rpcs3/Emu/Cell/lv2/sys_vm.cpp | 79 +++++++++++++++++++++++++---------- rpcs3/Emu/Cell/lv2/sys_vm.h | 3 +- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_vm.cpp b/rpcs3/Emu/Cell/lv2/sys_vm.cpp index 42ed234b02..bb684e3a03 100644 --- a/rpcs3/Emu/Cell/lv2/sys_vm.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_vm.cpp @@ -17,12 +17,6 @@ sys_vm_t::~sys_vm_t() { // Free ID g_ids[addr >> 28].release(id_manager::id_traits::invalid); - - // Free block - verify(HERE), vm::unmap(addr); - - // Return memory - ct->used -= psize; } LOG_CHANNEL(sys_vm); @@ -92,7 +86,16 @@ error_code sys_vm_unmap(ppu_thread& ppu, u32 addr) } // Free block and info - if (!idm::remove(sys_vm_t::find_id(addr))) + const auto vmo = idm::withdraw(sys_vm_t::find_id(addr), [&](sys_vm_t& vmo) + { + // Free block + verify(HERE), vm::unmap(addr); + + // Return memory + vmo.ct->used -= vmo.psize; + }); + + if (!vmo) { return CELL_EINVAL; } @@ -111,21 +114,32 @@ error_code sys_vm_append_memory(ppu_thread& ppu, u32 addr, u32 size) return CELL_EINVAL; } - const auto block = idm::get(sys_vm_t::find_id(addr)); + const auto block = idm::check(sys_vm_t::find_id(addr), [&](sys_vm_t& vmo) -> CellError + { + if (vmo.addr != addr) + { + return CELL_EINVAL; + } - if (!block || block->addr != addr) + if (!vmo.ct->take(size)) + { + return CELL_ENOMEM; + } + + vmo.psize += size; + return {}; + }); + + if (!block) { return CELL_EINVAL; } - std::lock_guard lock(block->mutex); - - if (!block->ct->take(size)) + if (block.ret) { - return CELL_ENOMEM; + return block.ret; } - block->psize += size; return CELL_OK; } @@ -140,22 +154,43 @@ error_code sys_vm_return_memory(ppu_thread& ppu, u32 addr, u32 size) return CELL_EINVAL; } - const auto block = idm::get(sys_vm_t::find_id(addr)); + const auto block = idm::check(sys_vm_t::find_id(addr), [&](sys_vm_t& vmo) -> CellError + { + if (vmo.addr != addr) + { + return CELL_EINVAL; + } - if (!block || block->addr != addr) + auto [_, ok] = vmo.psize.fetch_op([&](u32& value) + { + if (value < 0x100000ull + size) + { + return false; + } + + value -= size; + return true; + }); + + if (!ok) + { + return CELL_EBUSY; + } + + vmo.ct->used -= size; + return {}; + }); + + if (!block) { return CELL_EINVAL; } - std::lock_guard lock(block->mutex); - - if (u64{block->psize} < u64{0x100000} + size) + if (block.ret) { - return CELL_EBUSY; + return block.ret; } - block->psize -= size; - block->ct->used -= size; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_vm.h b/rpcs3/Emu/Cell/lv2/sys_vm.h index 947277f508..cd2d899de4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_vm.h +++ b/rpcs3/Emu/Cell/lv2/sys_vm.h @@ -38,8 +38,7 @@ struct sys_vm_t lv2_memory_container* const ct; const u32 addr; const u32 size; - u32 psize; - shared_mutex mutex; + atomic_t psize; sys_vm_t(u32 addr, u32 vsize, lv2_memory_container* ct, u32 psize); ~sys_vm_t();