You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.2 KiB
82 lines
2.2 KiB
#include <stdexcept>
|
|
#include <cassert>
|
|
#include <sys/mman.h>
|
|
#include "mmap_manager.h"
|
|
|
|
mmap_manager_t::mmap_manager_t(uint64_t mmap_size)
|
|
{
|
|
this->mmap_size = mmap_size;
|
|
}
|
|
|
|
mmap_manager_t::~mmap_manager_t()
|
|
{
|
|
for (auto & kv: past_buffers)
|
|
{
|
|
munmap(kv.second.addr, kv.second.size);
|
|
}
|
|
if (active_buffer.addr != NULL)
|
|
{
|
|
munmap(active_buffer.addr, active_buffer.size);
|
|
}
|
|
}
|
|
|
|
void *mmap_manager_t::alloc(uint64_t size)
|
|
{
|
|
if (!active_buffer.addr || (active_buffer.pos + size) > active_buffer.size)
|
|
{
|
|
if (active_buffer.addr)
|
|
{
|
|
if (active_buffer.freed >= active_buffer.pos)
|
|
munmap(active_buffer.addr, active_buffer.size);
|
|
else
|
|
past_buffers[active_buffer.addr] = active_buffer;
|
|
active_buffer = { 0 };
|
|
}
|
|
uint64_t new_size = size < mmap_size ? mmap_size : size;
|
|
void *buf = mmap(NULL, new_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
if (!buf)
|
|
throw std::runtime_error(std::string("can't mmap "+std::to_string(new_size)+" bytes"));
|
|
active_buffer = {
|
|
.addr = buf,
|
|
.size = new_size,
|
|
.freed = 0,
|
|
.pos = 0,
|
|
};
|
|
}
|
|
void *res = active_buffer.addr + active_buffer.pos;
|
|
active_buffer.pos += size;
|
|
return res;
|
|
}
|
|
|
|
void mmap_manager_t::free(void *addr, uint64_t size)
|
|
{
|
|
auto it = past_buffers.upper_bound(addr);
|
|
if (it != past_buffers.begin())
|
|
{
|
|
if (it == past_buffers.end())
|
|
{
|
|
it--;
|
|
if (addr < it->second.addr || addr >= it->second.addr+it->second.size)
|
|
it = past_buffers.end();
|
|
}
|
|
else
|
|
it--;
|
|
}
|
|
else
|
|
it = past_buffers.end();
|
|
if (it != past_buffers.end())
|
|
{
|
|
assert(addr >= it->second.addr && addr+size <= it->second.addr+it->second.size);
|
|
it->second.freed += size;
|
|
if (it->second.freed >= it->second.pos)
|
|
{
|
|
munmap(it->second.addr, it->second.size);
|
|
past_buffers.erase(it);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(addr < active_buffer.addr+active_buffer.size);
|
|
active_buffer.freed += size;
|
|
}
|
|
}
|
|
|