|
|
|
@ -39,7 +39,7 @@ |
|
|
|
|
#include <stddef.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* #define DEBUGMPOOL */ |
|
|
|
|
#define DEBUGMPOOL |
|
|
|
|
#ifdef DEBUGMPOOL |
|
|
|
|
#include <stdio.h> |
|
|
|
|
FILE *lfd = NULL; |
|
|
|
@ -50,16 +50,16 @@ FILE *lfd = NULL; |
|
|
|
|
|
|
|
|
|
#include "mpool.h" |
|
|
|
|
|
|
|
|
|
//#define MIN_FRAGSIZE 4096 /* 1m2.282s */
|
|
|
|
|
//#define MIN_FRAGSIZE 8192 /* 0m46.652s */
|
|
|
|
|
//#define MIN_FRAGSIZE 16384 /* 0m8.365s */
|
|
|
|
|
//#define MIN_FRAGSIZE 32768 /* 0m3.788s */
|
|
|
|
|
//#define MIN_FRAGSIZE 65536 /* 0m2.759s */
|
|
|
|
|
//#define MIN_FRAGSIZE 131072 /* 0m2.445s */
|
|
|
|
|
/* #define MIN_FRAGSIZE 4096 /\* 1m2.282s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 8192 /\* 0m46.652s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 16384 /\* 0m8.365s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 32768 /\* 0m3.788s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 65536 /\* 0m2.759s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 131072 /\* 0m2.445s *\/ */ |
|
|
|
|
#define MIN_FRAGSIZE 262144 /* 0m2.343s */ |
|
|
|
|
//#define MIN_FRAGSIZE 524288 /* 0m2.387s */
|
|
|
|
|
//#define MIN_FRAGSIZE 1048576 /* 0m2.392s */
|
|
|
|
|
//#define MIN_FRAGSIZE 2097152 /* 0m2.402s */
|
|
|
|
|
/* #define MIN_FRAGSIZE 524288 /\* 0m2.387s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 1048576 /\* 0m2.392s *\/ */ |
|
|
|
|
/* #define MIN_FRAGSIZE 2097152 /\* 0m2.402s *\/ */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct FRAG { |
|
|
|
@ -69,37 +69,44 @@ struct FRAG { |
|
|
|
|
}; |
|
|
|
|
#define FRAG_OVERHEAD (offsetof(struct FRAG, fake)) |
|
|
|
|
|
|
|
|
|
#define align_to_voidptr(size) (((size) / sizeof(void *) + ((size) % sizeof(void *) != 0)) * sizeof(void *)) |
|
|
|
|
#define roundup(size) (FRAG_OVERHEAD + align_to_voidptr(size)) |
|
|
|
|
|
|
|
|
|
static unsigned int align_to_pagesize(struct MP *mp, unsigned int size) { |
|
|
|
|
return (size / mp->psize + (size % mp->psize != 0)) * mp->psize; |
|
|
|
|
} |
|
|
|
|
static unsigned int align_to_voidptr(unsigned int size) { |
|
|
|
|
return (size / sizeof(void *) + (size % sizeof(void *) != 0)) * sizeof(void *); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* FIXME: use instead a bit2size table so we can spare bits and offer a better granularity */ |
|
|
|
|
static unsigned int to_bits(unsigned int size) { |
|
|
|
|
unsigned int i; |
|
|
|
|
for(i=0; i<32; i++) |
|
|
|
|
if((unsigned int)1<<i >= size) return i; |
|
|
|
|
for(i=0; i<FRAGSBITS; i++) |
|
|
|
|
if(fragsz[i] >= size) return i; |
|
|
|
|
return i; /* NOTREACHED */ |
|
|
|
|
} |
|
|
|
|
static unsigned int from_bits(unsigned int bits) { |
|
|
|
|
return 1<<bits; |
|
|
|
|
return fragsz[bits]; |
|
|
|
|
} |
|
|
|
|
/* static unsigned int to_bits(unsigned int size) { */ |
|
|
|
|
/* unsigned int i; */ |
|
|
|
|
/* for(i=0; i<32; i++) */ |
|
|
|
|
/* if((unsigned int)1<<i >= size) return i; */ |
|
|
|
|
/* return i; /\* NOTREACHED *\/ */ |
|
|
|
|
/* } */ |
|
|
|
|
/* static unsigned int from_bits(unsigned int bits) { */ |
|
|
|
|
/* return 1<<bits; */ |
|
|
|
|
/* } */ |
|
|
|
|
|
|
|
|
|
struct MP *mp_create() { |
|
|
|
|
struct MP mp, *mp_p; |
|
|
|
|
unsigned int sz; |
|
|
|
|
memset(&mp, 0, sizeof(mp)); |
|
|
|
|
mp.psize = getpagesize(); |
|
|
|
|
#ifdef DEBUGMPOOL |
|
|
|
|
lfd = fopen("mmpool_log", "w"); |
|
|
|
|
#endif |
|
|
|
|
mp.fd = open("/dev/zero", O_RDWR, 0); |
|
|
|
|
mp.top = align_to_pagesize(&mp, MIN_FRAGSIZE + 0*sizeof(mp)); |
|
|
|
|
sz = align_to_pagesize(&mp, MIN_FRAGSIZE); |
|
|
|
|
mp.mpm.usize = align_to_voidptr(sizeof(struct MPMAP)); |
|
|
|
|
mp.mpm.size = mp.top - align_to_voidptr(sizeof(mp)); |
|
|
|
|
if ((mp_p = (struct MP *)mmap(NULL, mp.top, PROT_READ | PROT_WRITE, MAP_PRIVATE, mp.fd, 0)) == MAP_FAILED) |
|
|
|
|
mp.mpm.size = sz - align_to_voidptr(sizeof(mp)); |
|
|
|
|
if ((mp_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) |
|
|
|
|
return NULL; |
|
|
|
|
memcpy(mp_p, &mp, sizeof(mp)); |
|
|
|
|
spam("Map created @ %p->%p - size %u out of %u\n", mp_p, (void*)mp_p + mp.mpm.size, mp.mpm.usize, mp.mpm.size); |
|
|
|
@ -108,7 +115,6 @@ struct MP *mp_create() { |
|
|
|
|
|
|
|
|
|
void mp_destroy(struct MP *mp) { |
|
|
|
|
struct MPMAP *mpm_next = mp->mpm.next, *mpm; |
|
|
|
|
close(mp->fd); |
|
|
|
|
while((mpm = mpm_next)) { |
|
|
|
|
mpm_next = mpm->next; |
|
|
|
|
munmap((void *)mpm, mpm->size); |
|
|
|
@ -148,19 +154,21 @@ void *mp_malloc(struct MP *mp, size_t size) { |
|
|
|
|
struct FRAG *f = NULL; |
|
|
|
|
struct MPMAP *mpm = &mp->mpm; |
|
|
|
|
|
|
|
|
|
// check_all(mp);
|
|
|
|
|
/* check_all(mp); */ |
|
|
|
|
if (!size) return NULL; |
|
|
|
|
|
|
|
|
|
j = sbits+2; |
|
|
|
|
if (j<7) j = 7; |
|
|
|
|
if (j > 32) j = 32; |
|
|
|
|
|
|
|
|
|
j=sbits; |
|
|
|
|
|
|
|
|
|
for (i=sbits; i<j; i++) |
|
|
|
|
if((f = mp->avail[i])) break; |
|
|
|
|
|
|
|
|
|
/* Case 1: We have a free'd frag */ |
|
|
|
|
if(f) { |
|
|
|
|
spam("malloc %p size %u (freed)\n"), f, size; |
|
|
|
|
spam("malloc %p size %u (freed)\n", f, roundup(size)); |
|
|
|
|
mp->avail[i] = f->next; |
|
|
|
|
return &f->fake; |
|
|
|
|
} |
|
|
|
@ -171,7 +179,7 @@ void *mp_malloc(struct MP *mp, size_t size) { |
|
|
|
|
while(mpm) { |
|
|
|
|
if(mpm->size - mpm->usize >= needed) { |
|
|
|
|
f = (struct FRAG *)((void *)mpm + mpm->usize); |
|
|
|
|
spam("malloc %p size %u (hole)\n", f, size); |
|
|
|
|
spam("malloc %p size %u (hole)\n", f, roundup(size)); |
|
|
|
|
mpm->usize += needed; |
|
|
|
|
f->sbits = sbits; |
|
|
|
|
return &f->fake; |
|
|
|
@ -185,17 +193,16 @@ void *mp_malloc(struct MP *mp, size_t size) { |
|
|
|
|
else |
|
|
|
|
i = align_to_pagesize(mp, MIN_FRAGSIZE); |
|
|
|
|
|
|
|
|
|
if ((mpm = (struct MPMAP *)mmap(NULL, i, PROT_READ | PROT_WRITE, MAP_PRIVATE, mp->fd, mp->top)) == MAP_FAILED) { |
|
|
|
|
if ((mpm = (struct MPMAP *)mmap(NULL, i, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) { |
|
|
|
|
spam("failed to alloc %u bytes (%u requested)\n", i, size); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
mp->top += i; |
|
|
|
|
mpm->size = i; |
|
|
|
|
mpm->usize = needed + align_to_voidptr(sizeof(*mpm)); |
|
|
|
|
mpm->next = mp->mpm.next; |
|
|
|
|
mp->mpm.next = mpm; |
|
|
|
|
f = (struct FRAG *)((void *)mpm + align_to_voidptr(sizeof(*mpm))); |
|
|
|
|
spam("malloc %p size %u (new map)\n", f, size); |
|
|
|
|
spam("malloc %p size %u (new map)\n", f, roundup(size)); |
|
|
|
|
f->sbits = sbits; |
|
|
|
|
return &f->fake; |
|
|
|
|
} |
|
|
|
|