Implement vm::find_map; improve memory allocation

Add vm::user64k and vm::user1m constants
Remove vm::user_space, unreserve it
This commit is contained in:
Nekotekina 2018-08-13 19:15:56 +03:00
parent 9578e1e923
commit aa4040bb7b
10 changed files with 139 additions and 67 deletions

View file

@ -711,6 +711,41 @@ namespace vm
return imp_used(lock);
}
static bool _test_map(u32 addr, u32 size)
{
for (auto& block : g_locations)
{
if (block && block->addr >= addr && block->addr <= addr + size - 1)
{
return false;
}
if (block && addr >= block->addr && addr <= block->addr + block->size - 1)
{
return false;
}
}
return true;
}
static std::shared_ptr<block_t> _find_map(u32 size, u32 align, u64 flags)
{
for (u32 addr = ::align<u32>(0x20000000, align); addr < 0xC0000000; addr += align)
{
if (_test_map(addr, size))
{
auto block = std::make_shared<block_t>(addr, size, flags);
g_locations.emplace_back(block);
return block;
}
}
return nullptr;
}
std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags)
{
vm::writer_lock lock(0);
@ -720,17 +755,9 @@ namespace vm
fmt::throw_exception("Invalid arguments (addr=0x%x, size=0x%x)" HERE, addr, size);
}
for (auto& block : g_locations)
if (!_test_map(addr, size))
{
if (block->addr >= addr && block->addr <= addr + size - 1)
{
return nullptr;
}
if (addr >= block->addr && addr <= block->addr + block->size - 1)
{
return nullptr;
}
return nullptr;
}
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
@ -748,6 +775,28 @@ namespace vm
return block;
}
std::shared_ptr<block_t> find_map(u32 orig_size, u32 align, u64 flags)
{
vm::writer_lock lock(0);
// Align to minimal page size
const u32 size = ::align(orig_size, 0x10000);
// Check alignment
if (align < 0x10000 || align != (0x80000000u >> ::cntlz32(align, true)))
{
fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)" HERE, size, align);
}
// Return if size is invalid
if (!size || size > 0x40000000)
{
return nullptr;
}
return _find_map(size, align, flags);
}
std::shared_ptr<block_t> unmap(u32 addr, bool must_be_empty)
{
vm::writer_lock lock(0);
@ -756,6 +805,16 @@ namespace vm
{
if (*it && (*it)->addr == addr)
{
if (must_be_empty && (*it)->flags & 0x3)
{
continue;
}
if (!must_be_empty && ((*it)->flags & 0x3) != 2)
{
continue;
}
if (must_be_empty && (!it->unique() || (*it)->imp_used(lock)))
{
return *it;
@ -779,7 +838,25 @@ namespace vm
// return selected location
if (location < g_locations.size())
{
return g_locations[location];
auto& loc = g_locations[location];
if (!loc)
{
if (location == vm::user64k || location == vm::user1m)
{
g_mutex.lock_upgrade();
if (!loc)
{
// Deferred allocation
loc = _find_map(0x10000000, 0x10000000, location == vm::user64k ? 0x201 : 0x401);
}
g_mutex.lock_degrade();
}
}
return loc;
}
return nullptr;
@ -788,7 +865,7 @@ namespace vm
// search location by address
for (auto& block : g_locations)
{
if (addr >= block->addr && addr <= block->addr + block->size - 1)
if (block && addr >= block->addr && addr <= block->addr + block->size - 1)
{
return block;
}
@ -804,9 +881,10 @@ namespace vm
g_locations =
{
std::make_shared<block_t>(0x00010000, 0x1FFF0000), // main
std::make_shared<block_t>(0x20000000, 0x10000000), // user
std::make_shared<block_t>(0xC0000000, 0x10000000), // video
std::make_shared<block_t>(0xD0000000, 0x10000000), // stack
nullptr, // user 64k pages
nullptr, // user 1m pages
std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved
};
}