[util] regions: pinned objects, and big allocations
This commit is contained in:
parent
dfa3c39cec
commit
b0c3c9e013
|
@ -5,13 +5,13 @@
|
||||||
static inline void* underlying_alloc(size_t siz)
|
static inline void* underlying_alloc(size_t siz)
|
||||||
{
|
{
|
||||||
void* p = malloc(siz);
|
void* p = malloc(siz);
|
||||||
// printf("[region] allocate %zu ==> %p\n", sz, p);
|
// printf("[region] allocate %zu ==> %p\n", siz, p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void underlying_free(void* p)
|
static inline void underlying_free(void* p)
|
||||||
{
|
{
|
||||||
// printf("[regoin] free %p\n", p);
|
// printf("[region] free %p\n", p);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,12 @@ struct rgn_block {
|
||||||
char data[0];
|
char data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rgn_pinned_obj {
|
||||||
|
struct rgn_pinned_obj* next;
|
||||||
|
void* obj;
|
||||||
|
void (*dtor)(void*);
|
||||||
|
};
|
||||||
|
|
||||||
void rgn_init(struct rgn* rgn, size_t pg_size)
|
void rgn_init(struct rgn* rgn, size_t pg_size)
|
||||||
{
|
{
|
||||||
rgn->pg_size = pg_size;
|
rgn->pg_size = pg_size;
|
||||||
|
@ -28,10 +34,14 @@ void rgn_init(struct rgn* rgn, size_t pg_size)
|
||||||
rgn->here = rgn->eob = NULL;
|
rgn->here = rgn->eob = NULL;
|
||||||
rgn->unused_blocks = NULL;
|
rgn->unused_blocks = NULL;
|
||||||
rgn->used_blocks = NULL;
|
rgn->used_blocks = NULL;
|
||||||
|
rgn->pinned = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unused_blocks(struct rgn_block* b0)
|
void rgn_cleanup(struct rgn* rgn)
|
||||||
{
|
{
|
||||||
|
rgn_clear(rgn);
|
||||||
|
|
||||||
|
struct rgn_block* b0 = rgn->unused_blocks;
|
||||||
struct rgn_block* b1;
|
struct rgn_block* b1;
|
||||||
for (; b0 != NULL; b0 = b1) {
|
for (; b0 != NULL; b0 = b1) {
|
||||||
b1 = b0->next;
|
b1 = b0->next;
|
||||||
|
@ -39,14 +49,13 @@ static void unused_blocks(struct rgn_block* b0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rgn_cleanup(struct rgn* rgn)
|
|
||||||
{
|
|
||||||
unused_blocks(rgn->unused_blocks);
|
|
||||||
unused_blocks(rgn->used_blocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rgn_clear(struct rgn* rgn)
|
void rgn_clear(struct rgn* rgn)
|
||||||
{
|
{
|
||||||
|
struct rgn_pinned_obj* pin = rgn->pinned;
|
||||||
|
for (; pin != NULL; pin = pin->next) {
|
||||||
|
pin->dtor(pin->obj);
|
||||||
|
}
|
||||||
|
|
||||||
struct rgn_block* uub = rgn->unused_blocks;
|
struct rgn_block* uub = rgn->unused_blocks;
|
||||||
struct rgn_block* b0 = rgn->used_blocks;
|
struct rgn_block* b0 = rgn->used_blocks;
|
||||||
struct rgn_block* b1;
|
struct rgn_block* b1;
|
||||||
|
@ -56,35 +65,35 @@ void rgn_clear(struct rgn* rgn)
|
||||||
uub = b0;
|
uub = b0;
|
||||||
}
|
}
|
||||||
rgn->unused_blocks = uub;
|
rgn->unused_blocks = uub;
|
||||||
rgn->used_blocks = NULL;
|
|
||||||
rgn->here = rgn->eob = NULL;
|
rgn->here = rgn->eob = NULL;
|
||||||
|
rgn->used_blocks = NULL;
|
||||||
|
rgn->pinned = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void use_block(struct rgn* rgn, struct rgn_block* b)
|
static inline void new_block(struct rgn* rgn)
|
||||||
{
|
{
|
||||||
|
struct rgn_block* b = rgn->unused_blocks;
|
||||||
|
if (b != NULL) {
|
||||||
|
rgn->unused_blocks = b->next;
|
||||||
|
} else {
|
||||||
|
b = underlying_alloc(rgn->pg_size);
|
||||||
|
b->eob = ((char*) b) + rgn->pg_size;
|
||||||
|
}
|
||||||
|
|
||||||
b->next = rgn->used_blocks;
|
b->next = rgn->used_blocks;
|
||||||
rgn->used_blocks = b;
|
rgn->used_blocks = b;
|
||||||
rgn->here = b->data;
|
rgn->here = b->data;
|
||||||
rgn->eob = b->eob;
|
rgn->eob = b->eob;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void new_block(struct rgn* rgn)
|
|
||||||
{
|
|
||||||
struct rgn_block* b0 = rgn->unused_blocks;
|
|
||||||
if (b0 != NULL) {
|
|
||||||
rgn->unused_blocks = b0->next;
|
|
||||||
} else {
|
|
||||||
b0 = underlying_alloc(rgn->pg_size);
|
|
||||||
b0->eob = ((char*) b0) + rgn->pg_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
use_block(rgn, b0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz)
|
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz)
|
||||||
{
|
{
|
||||||
// TODO: relax this
|
if (siz > rgn->max_alloc_size) {
|
||||||
ASSERT(siz <= rgn->max_alloc_size, "allocation too big!");
|
void* ptr = underlying_alloc(siz);
|
||||||
|
rgn_pin(rgn, ptr, underlying_free);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
char* there = rgn->here + siz;
|
char* there = rgn->here + siz;
|
||||||
if (there > rgn->eob) {
|
if (there > rgn->eob) {
|
||||||
|
@ -97,6 +106,15 @@ void* ralloc_assume_aligned(struct rgn* rgn, size_t siz)
|
||||||
return here;
|
return here;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rgn_pin(struct rgn* rgn, void* obj, void (*dtor)(void*))
|
||||||
|
{
|
||||||
|
struct rgn_pinned_obj* pin = ralloc(rgn, sizeof(struct rgn_pinned_obj));
|
||||||
|
pin->next = rgn->pinned;
|
||||||
|
pin->obj = obj;
|
||||||
|
pin->dtor = dtor;
|
||||||
|
rgn->pinned = pin;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void rgn_print_stats(struct rgn* rgn, FILE* out)
|
void rgn_print_stats(struct rgn* rgn, FILE* out)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct rgn_block;
|
struct rgn_block;
|
||||||
|
struct rgn_pinned_obj;
|
||||||
|
|
||||||
struct rgn {
|
struct rgn {
|
||||||
size_t pg_size;
|
size_t pg_size;
|
||||||
|
@ -11,8 +12,13 @@ struct rgn {
|
||||||
char* eob;
|
char* eob;
|
||||||
struct rgn_block* unused_blocks;
|
struct rgn_block* unused_blocks;
|
||||||
struct rgn_block* used_blocks;
|
struct rgn_block* used_blocks;
|
||||||
|
struct rgn_pinned_obj* pinned;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Init / cleanup
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define SMALL 1024
|
#define SMALL 1024
|
||||||
#define MEDIUM (16*1024)
|
#define MEDIUM (16*1024)
|
||||||
#define LARGE (1024*1024)
|
#define LARGE (1024*1024)
|
||||||
|
@ -23,6 +29,10 @@ void rgn_clear(struct rgn* rgn);
|
||||||
|
|
||||||
// void rgn_print_stats(struct rgn* rgn, FILE* out);
|
// void rgn_print_stats(struct rgn* rgn, FILE* out);
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Allocating and pinning
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz);
|
void* ralloc_assume_aligned(struct rgn* rgn, size_t siz);
|
||||||
|
|
||||||
static inline void* ralloc(struct rgn* rgn, size_t siz)
|
static inline void* ralloc(struct rgn* rgn, size_t siz)
|
||||||
|
@ -33,6 +43,12 @@ static inline void* ralloc(struct rgn* rgn, size_t siz)
|
||||||
return ralloc_assume_aligned(rgn, siz);
|
return ralloc_assume_aligned(rgn, siz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rgn_pin(struct rgn* rgn, void* obj, void (*dtor)(void*));
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Derived utilities
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static inline void* rmemdup(struct rgn* rgn, const void* ptr, size_t siz)
|
static inline void* rmemdup(struct rgn* rgn, const void* ptr, size_t siz)
|
||||||
{
|
{
|
||||||
void* new = ralloc(rgn, siz);
|
void* new = ralloc(rgn, siz);
|
||||||
|
|
Loading…
Reference in New Issue