Partial commit: sys_memory, sys_mmapper

This commit is contained in:
Nekotekina 2016-05-25 21:04:08 +03:00
parent f5e65e4ad9
commit 96728a83f6
13 changed files with 366 additions and 375 deletions

View file

@ -24,6 +24,8 @@
#include "wait_engine.h"
#include <mutex>
namespace vm
{
thread_local u64 g_tls_fault_count{};
@ -482,7 +484,7 @@ namespace vm
return true;
}
u32 alloc(u32 size, memory_location_t location, u32 align)
u32 alloc(u32 size, memory_location_t location, u32 align, u32 sup)
{
const auto block = get(location);
@ -491,10 +493,10 @@ namespace vm
throw EXCEPTION("Invalid memory location (%d)", location);
}
return block->alloc(size, align);
return block->alloc(size, align, sup);
}
u32 falloc(u32 addr, u32 size, memory_location_t location)
u32 falloc(u32 addr, u32 size, memory_location_t location, u32 sup)
{
const auto block = get(location, addr);
@ -503,10 +505,10 @@ namespace vm
throw EXCEPTION("Invalid memory location (%d, addr=0x%x)", location, addr);
}
return block->falloc(addr, size);
return block->falloc(addr, size, sup);
}
bool dealloc(u32 addr, memory_location_t location)
u32 dealloc(u32 addr, memory_location_t location, u32* sup_out)
{
const auto block = get(location, addr);
@ -515,7 +517,7 @@ namespace vm
throw EXCEPTION("Invalid memory location (%d, addr=0x%x)", location, addr);
}
return block->dealloc(addr);
return block->dealloc(addr, sup_out);
}
void dealloc_verbose_nothrow(u32 addr, memory_location_t location) noexcept
@ -535,9 +537,9 @@ namespace vm
}
}
bool block_t::try_alloc(u32 addr, u32 size)
bool block_t::try_alloc(u32 addr, u32 size, u32 sup)
{
// check if memory area is already mapped
// Check if memory area is already mapped
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
{
if (g_pages[i])
@ -546,86 +548,70 @@ namespace vm
}
}
// try to reserve "physical" memory
if (!used.atomic_op([=](u32& used) -> bool
{
if (used > this->size)
{
throw EXCEPTION("Unexpected memory amount used (0x%x)", used);
}
if (used + size > this->size)
{
return false;
}
used += size;
return true;
}))
{
return false;
}
// map memory pages
// Map "real" memory pages
_page_map(addr, size, page_readable | page_writable);
// add entry
// Add entry
m_map[addr] = size;
// Add supplementary info if necessary
if (sup) m_sup[addr] = sup;
return true;
}
block_t::block_t(u32 addr, u32 size, u64 flags)
: addr(addr)
, size(size)
, flags(flags)
{
}
block_t::~block_t()
{
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
// deallocate all memory
// Deallocate all memory
for (auto& entry : m_map)
{
_page_unmap(entry.first, entry.second);
}
}
u32 block_t::alloc(u32 size, u32 align)
u32 block_t::alloc(u32 size, u32 align, u32 sup)
{
std::lock_guard<std::mutex> lock(m_mutex);
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
// align to minimal page size
// Align to minimal page size
size = ::align(size, 4096);
// check alignment (it's page allocation, so passing small values there is just silly)
// Check alignment (it's page allocation, so passing small values there is just silly)
if (align < 4096 || align != (0x80000000u >> cntlz32(align)))
{
throw EXCEPTION("Invalid alignment (size=0x%x, align=0x%x)", size, align);
}
// return if size is invalid
// Return if size is invalid
if (!size || size > this->size)
{
return 0;
}
// search for an appropriate place (unoptimized)
// Search for an appropriate place (unoptimized)
for (u32 addr = ::align(this->addr, align); addr < this->addr + this->size - 1; addr += align)
{
if (try_alloc(addr, size))
if (try_alloc(addr, size, sup))
{
return addr;
}
if (used + size > this->size)
{
return 0;
}
}
return 0;
}
u32 block_t::falloc(u32 addr, u32 size)
u32 block_t::falloc(u32 addr, u32 size, u32 sup)
{
std::lock_guard<std::mutex> lock(m_mutex);
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
// align to minimal page size
size = ::align(size, 4096);
@ -636,7 +622,7 @@ namespace vm
return 0;
}
if (!try_alloc(addr, size))
if (!try_alloc(addr, size, sup))
{
return 0;
}
@ -644,9 +630,9 @@ namespace vm
return addr;
}
bool block_t::dealloc(u32 addr)
u32 block_t::dealloc(u32 addr, u32* sup_out)
{
std::lock_guard<std::mutex> lock(m_mutex);
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
const auto found = m_map.find(addr);
@ -654,19 +640,36 @@ namespace vm
{
const u32 size = found->second;
// remove entry
// Remove entry
m_map.erase(found);
// return "physical" memory
used -= size;
// Unmap "real" memory pages
_page_unmap(addr, size);
// unmap memory pages
std::lock_guard<reservation_mutex_t>{ g_reservation_mutex }, _page_unmap(addr, size);
// Write supplementary info if necessary
if (sup_out) *sup_out = m_sup[addr];
return true;
// Remove supplementary info
m_sup.erase(addr);
return size;
}
return false;
return 0;
}
u32 block_t::used()
{
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
u32 result = 0;
for (auto& entry : m_map)
{
result += entry.second;
}
return result;
}
std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags)
@ -706,7 +709,7 @@ namespace vm
return block;
}
std::shared_ptr<block_t> unmap(u32 addr)
std::shared_ptr<block_t> unmap(u32 addr, bool must_be_empty)
{
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
@ -714,6 +717,11 @@ namespace vm
{
if (*it && (*it)->addr == addr)
{
if (must_be_empty && (!it->unique() || (*it)->used()))
{
return *it;
}
auto block = std::move(*it);
g_locations.erase(it);
return block;