344 lines
5.9 KiB
C
344 lines
5.9 KiB
C
#include "nmx_palloc.h"
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
typedef struct nmx_pool_large_s nmx_pool_large_t;
|
|
|
|
struct nmx_pool_large_s {
|
|
nmx_pool_large_t *next;
|
|
void *alloc;
|
|
};
|
|
|
|
typedef struct {
|
|
unsigned char *last;
|
|
unsigned char *end;
|
|
nmx_pool_t *next;
|
|
unsigned int failed;
|
|
} nmx_pool_data_t;
|
|
|
|
struct nmx_pool_s {
|
|
|
|
nmx_pool_data_t d;
|
|
size_t max;
|
|
nmx_pool_t *current;
|
|
nmx_pool_large_t *large;
|
|
};
|
|
|
|
#define nmx_free free
|
|
|
|
#define nmx_align_ptr(p, a) \
|
|
(unsigned char *) (((unsigned long ) (p) + ((unsigned long ) a - 1)) & ~((unsigned long ) a - 1))
|
|
|
|
void * nmx_alloc(size_t size)
|
|
{
|
|
void *p;
|
|
p = malloc(size);
|
|
return p;
|
|
}
|
|
|
|
|
|
void *nmx_calloc(size_t size)
|
|
{
|
|
void *p;
|
|
p = nmx_alloc(size);
|
|
if (p) {
|
|
memset(p,0,size);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
void *nmx_realloc(void *p, size_t size)
|
|
{
|
|
if(p) {
|
|
return realloc (p, size);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void *nmx_memalign(size_t alignment, size_t size)
|
|
{
|
|
void *p=NULL;
|
|
posix_memalign(&p, alignment, size);
|
|
return p;
|
|
}
|
|
|
|
size_t nmx_pagesize = 0;
|
|
|
|
//#define nmx_MAX_ALLOC_FROM_POOL (nmx_pagesize - 1)
|
|
|
|
#define NMX_MAX_ALLOC_FROM_POOL (nmx_pagesize == 0 ? (nmx_pagesize = getpagesize() -1) : (nmx_pagesize))
|
|
|
|
#define NMX_POOL_ALIGNMENT 16
|
|
|
|
|
|
static void *nmx_palloc_block(nmx_pool_t *pool, size_t size);
|
|
static void *nmx_palloc_large(nmx_pool_t *pool, size_t size);
|
|
|
|
|
|
nmx_pool_t *
|
|
nmx_create_pool(size_t size)
|
|
{
|
|
nmx_pool_t *p;
|
|
|
|
p = (nmx_pool_t *)nmx_memalign(NMX_POOL_ALIGNMENT, size);
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
p->d.last = (unsigned char *) p + sizeof(nmx_pool_t);
|
|
p->d.end = (unsigned char *) p + size;
|
|
p->d.next = NULL;
|
|
p->d.failed = 0;
|
|
|
|
size = size - sizeof(nmx_pool_t);
|
|
p->max = (size < NMX_MAX_ALLOC_FROM_POOL) ? size : NMX_MAX_ALLOC_FROM_POOL;
|
|
|
|
p->current = p;
|
|
p->large = NULL;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
void
|
|
nmx_destroy_pool(nmx_pool_t *pool)
|
|
{
|
|
nmx_pool_t *p, *n;
|
|
nmx_pool_large_t *l;
|
|
|
|
for (l = pool->large; l; l = l->next) {
|
|
|
|
if (l->alloc) {
|
|
nmx_free(l->alloc);
|
|
}
|
|
}
|
|
|
|
for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
|
|
nmx_free(p);
|
|
|
|
if (n == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
nmx_reset_pool(nmx_pool_t *pool)
|
|
{
|
|
nmx_pool_t *p;
|
|
nmx_pool_large_t *l;
|
|
|
|
for (l = pool->large; l; l = l->next) {
|
|
if (l->alloc) {
|
|
nmx_free(l->alloc);
|
|
}
|
|
}
|
|
|
|
for (p = pool; p; p = p->d.next) {
|
|
p->d.last = (unsigned char *) p + sizeof(nmx_pool_t);
|
|
p->d.failed = 0;
|
|
}
|
|
|
|
pool->current = pool;
|
|
pool->large = NULL;
|
|
}
|
|
|
|
|
|
void *
|
|
nmx_palloc(nmx_pool_t *pool, size_t size)
|
|
{
|
|
unsigned char *m;
|
|
nmx_pool_t *p;
|
|
|
|
if (size <= pool->max) {
|
|
|
|
p = pool->current;
|
|
|
|
do {
|
|
m = nmx_align_ptr(p->d.last, NMX_POOL_ALIGNMENT);
|
|
|
|
if ((size_t) (p->d.end - m) >= size) {
|
|
p->d.last = m + size;
|
|
|
|
return m;
|
|
}
|
|
|
|
p = p->d.next;
|
|
|
|
} while (p);
|
|
|
|
return nmx_palloc_block(pool, size);
|
|
}
|
|
|
|
|
|
|
|
return nmx_palloc_large(pool, size);
|
|
}
|
|
|
|
|
|
void *
|
|
nmx_pnalloc(nmx_pool_t *pool, size_t size)
|
|
{
|
|
unsigned char *m;
|
|
nmx_pool_t *p;
|
|
|
|
|
|
if (size <= pool->max) {
|
|
|
|
p = pool->current;
|
|
|
|
do {
|
|
m = p->d.last;
|
|
|
|
if ((size_t) (p->d.end - m) >= size) {
|
|
p->d.last = m + size;
|
|
|
|
return m;
|
|
}
|
|
|
|
p = p->d.next;
|
|
|
|
} while (p);
|
|
|
|
return nmx_palloc_block(pool, size);
|
|
}
|
|
|
|
|
|
return nmx_palloc_large(pool, size);
|
|
}
|
|
|
|
|
|
static void *
|
|
nmx_palloc_block(nmx_pool_t *pool, size_t size)
|
|
{
|
|
unsigned char *m;
|
|
size_t psize;
|
|
nmx_pool_t *p, *new;
|
|
|
|
psize = (size_t) (pool->d.end - (unsigned char *) pool);
|
|
|
|
m = (unsigned char *)nmx_memalign(NMX_POOL_ALIGNMENT, psize);
|
|
if (m == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
new = (nmx_pool_t *) m;
|
|
|
|
new->d.end = m + psize;
|
|
new->d.next = NULL;
|
|
new->d.failed = 0;
|
|
|
|
m += sizeof(nmx_pool_data_t);
|
|
m = nmx_align_ptr(m, NMX_POOL_ALIGNMENT);
|
|
new->d.last = m + size;
|
|
|
|
for (p = pool->current; p->d.next; p = p->d.next) {
|
|
if (p->d.failed++ > 4) {
|
|
pool->current = p->d.next;
|
|
}
|
|
}
|
|
|
|
p->d.next = new;
|
|
|
|
return m;
|
|
}
|
|
|
|
|
|
static void *
|
|
nmx_palloc_large(nmx_pool_t *pool,size_t size)
|
|
{
|
|
void *p;
|
|
int n;
|
|
nmx_pool_large_t *large;
|
|
|
|
p = nmx_alloc(size);
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
n = 0;
|
|
|
|
for (large = pool->large; large; large = large->next) {
|
|
if (large->alloc == NULL) {
|
|
large->alloc = p;
|
|
return p;
|
|
}
|
|
|
|
if (n++ > 3) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
large = nmx_palloc(pool, sizeof(nmx_pool_large_t));
|
|
if (large == NULL) {
|
|
nmx_free(p);
|
|
return NULL;
|
|
}
|
|
|
|
large->alloc = p;
|
|
large->next = pool->large;
|
|
pool->large = large;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
void *
|
|
nmx_pmemalign(nmx_pool_t *pool, size_t size, size_t alignment)
|
|
{
|
|
void *p;
|
|
nmx_pool_large_t *large;
|
|
|
|
p = nmx_memalign(alignment, size);
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
large = nmx_palloc(pool, sizeof(nmx_pool_large_t));
|
|
if (large == NULL) {
|
|
nmx_free(p);
|
|
return NULL;
|
|
}
|
|
|
|
large->alloc = p;
|
|
large->next = pool->large;
|
|
pool->large = large;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
int
|
|
nmx_pfree(nmx_pool_t *pool, void *p)
|
|
{
|
|
nmx_pool_large_t *l;
|
|
|
|
for (l = pool->large; l; l = l->next) {
|
|
if (p == l->alloc) {
|
|
|
|
nmx_free(l->alloc);
|
|
l->alloc = NULL;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *
|
|
nmx_pcalloc(nmx_pool_t *pool, size_t size)
|
|
{
|
|
void *p;
|
|
|
|
p = nmx_palloc(pool, size);
|
|
if (p) {
|
|
memset(p, 0,size);
|
|
}
|
|
|
|
return p;
|
|
}
|