parent
a863013cb2
commit
6c3248a36c
@ -0,0 +1,82 @@ |
||||
#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; |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
#include <map> |
||||
|
||||
struct mmap_buffer_t |
||||
{ |
||||
void *addr = NULL; |
||||
uint64_t size = 0; |
||||
uint64_t freed = 0; |
||||
uint64_t pos = 0; |
||||
}; |
||||
|
||||
class mmap_manager_t |
||||
{ |
||||
protected: |
||||
uint64_t mmap_size = 32*1024*1024; |
||||
std::map<void*, mmap_buffer_t> past_buffers; |
||||
mmap_buffer_t active_buffer; |
||||
|
||||
public: |
||||
mmap_manager_t(uint64_t mmap_size = 32*1024*1024); |
||||
~mmap_manager_t(); |
||||
void *alloc(uint64_t size); |
||||
void free(void *addr, uint64_t size); |
||||
}; |
Loading…
Reference in new issue