Fix sys_vm_t destructor

It's not a destructor's job to free vm like this.
This commit is contained in:
Nekotekina 2019-10-17 19:24:34 +03:00
parent 5af8a9fbbc
commit 00895862e1
2 changed files with 58 additions and 24 deletions

View File

@ -17,12 +17,6 @@ sys_vm_t::~sys_vm_t()
{
// Free ID
g_ids[addr >> 28].release(id_manager::id_traits<sys_vm_t>::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>(sys_vm_t::find_id(addr)))
const auto vmo = idm::withdraw<sys_vm_t>(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>(sys_vm_t::find_id(addr));
const auto block = idm::check<sys_vm_t>(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>(sys_vm_t::find_id(addr));
const auto block = idm::check<sys_vm_t>(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;
}

View File

@ -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<u32> psize;
sys_vm_t(u32 addr, u32 vsize, lv2_memory_container* ct, u32 psize);
~sys_vm_t();