lay groundwork for more efficient and flexible allocators. add new sysdep/vm that provides access to additional features on Windows (large pages, autocommit). add Pool/Arena allocators that avoid overhead and support arbitrary storage (not just the expensive virtual memory allocator in DynArray)

This was SVN commit r10051.
This commit is contained in:
janwas
2011-08-21 11:00:09 +00:00
parent 3eb1ed0139
commit 881d3cebf4
22 changed files with 1604 additions and 197 deletions
+10 -28
View File
@@ -28,7 +28,7 @@
#include "lib/allocators/dynarray.h"
#include "lib/alignment.h"
#include "lib/allocators/page_aligned.h"
#include "lib/sysdep/vm.h"
static Status validate_da(DynArray* da)
@@ -39,7 +39,6 @@ static Status validate_da(DynArray* da)
const size_t max_size_pa = da->max_size_pa;
const size_t cur_size = da->cur_size;
const size_t pos = da->pos;
const int prot = da->prot;
// note: this happens if max_size == 0
// if(debug_IsPointerBogus(base))
@@ -52,8 +51,6 @@ static Status validate_da(DynArray* da)
WARN_RETURN(ERR::_4);
if(pos > cur_size || pos > max_size_pa)
WARN_RETURN(ERR::_5);
if(prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
WARN_RETURN(ERR::_6);
return INFO::OK;
}
@@ -63,17 +60,17 @@ static Status validate_da(DynArray* da)
Status da_alloc(DynArray* da, size_t max_size)
{
ENSURE(max_size != 0);
const size_t max_size_pa = Align<pageSize>(max_size);
u8* p = 0;
if(max_size_pa) // (avoid mmap failure)
RETURN_STATUS_IF_ERR(mem_Reserve(max_size_pa, &p));
u8* p = (u8*)vm::ReserveAddressSpace(max_size_pa);
if(!p)
return ERR::NO_MEM; // NOWARN (already done in vm)
da->base = p;
da->max_size_pa = max_size_pa;
da->cur_size = 0;
da->cur_size_pa = 0;
da->prot = PROT_READ|PROT_WRITE;
da->pos = 0;
CHECK_DA(da);
return INFO::OK;
@@ -84,15 +81,11 @@ Status da_free(DynArray* da)
{
CHECK_DA(da);
u8* p = da->base;
size_t size_pa = da->max_size_pa;
vm::ReleaseAddressSpace(da->base, da->max_size_pa);
// wipe out the DynArray for safety
// (must be done here because mem_Release may fail)
memset(da, 0, sizeof(*da));
if(size_pa)
RETURN_STATUS_IF_ERR(mem_Release(p, size_pa));
return INFO::OK;
}
@@ -113,19 +106,20 @@ Status da_set_size(DynArray* da, size_t new_size)
return ERR::LIMIT; // NOWARN
u8* end = da->base + cur_size_pa;
bool ok = true;
// expanding
if(size_delta_pa > 0)
RETURN_STATUS_IF_ERR(mem_Commit(end, size_delta_pa, da->prot));
ok = vm::Commit(uintptr_t(end), size_delta_pa);
// shrinking
else if(size_delta_pa < 0)
RETURN_STATUS_IF_ERR(mem_Decommit(end+size_delta_pa, -size_delta_pa));
ok = vm::Decommit(uintptr_t(end+size_delta_pa), -size_delta_pa);
// else: no change in page count, e.g. if going from size=1 to 2
// (we don't want mem_* to have to handle size=0)
da->cur_size = new_size;
da->cur_size_pa = new_size_pa;
CHECK_DA(da);
return INFO::OK;
return ok? INFO::OK : ERR::FAIL;
}
@@ -138,18 +132,6 @@ Status da_reserve(DynArray* da, size_t size)
}
Status da_set_prot(DynArray* da, int prot)
{
CHECK_DA(da);
da->prot = prot;
RETURN_STATUS_IF_ERR(mem_Protect(da->base, da->cur_size_pa, prot));
CHECK_DA(da);
return INFO::OK;
}
Status da_append(DynArray* da, const void* data, size_t size)
{
RETURN_STATUS_IF_ERR(da_reserve(da, size));