From 9e66f0816e6b6c191ba01ba209d5467b7fcd756d Mon Sep 17 00:00:00 2001 From: cedric Date: Thu, 31 Jul 2008 15:11:05 +0000 Subject: [PATCH] Add the chained_pool stuff from evas with some cleanup. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/proto/eina@35272 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/modules/Makefile.am | 2 +- src/modules/chained_pool/.cvsignore | 6 + src/modules/chained_pool/Makefile.am | 16 ++ src/modules/chained_pool/eina_chained_mempool.c | 201 ++++++++++++++++++++++++ 4 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 src/modules/chained_pool/.cvsignore create mode 100644 src/modules/chained_pool/Makefile.am create mode 100644 src/modules/chained_pool/eina_chained_mempool.c diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index 38cd204..11355f6 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = mm_policies +SUBDIRS = mm_policies chained_pool MAINTAINERCLEANFILES = \ Makefile.in \ No newline at end of file diff --git a/src/modules/chained_pool/.cvsignore b/src/modules/chained_pool/.cvsignore new file mode 100644 index 0000000..b9f26ab --- /dev/null +++ b/src/modules/chained_pool/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +*.la +*.lo +.libs +.deps diff --git a/src/modules/chained_pool/Makefile.am b/src/modules/chained_pool/Makefile.am new file mode 100644 index 0000000..a7da76a --- /dev/null +++ b/src/modules/chained_pool/Makefile.am @@ -0,0 +1,16 @@ +MAINTAINERCLEANFILES = \ +Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/include + +controllerdir = $(libdir)/eina/chained_pool/ +controller_LTLIBRARIES = eina_chained_mempool.la + +eina_chained_mempool_la_SOURCES = \ +eina_chained_mempool.c + +eina_chained_mempool_la_LIBADD = $(top_builddir)/src/lib/libeina.la +eina_chained_mempool_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +eina_chained_mempool_la_DEPENDENCIES = $(top_builddir)/src/lib/libeina.la diff --git a/src/modules/chained_pool/eina_chained_mempool.c b/src/modules/chained_pool/eina_chained_mempool.c new file mode 100644 index 0000000..9fa874b --- /dev/null +++ b/src/modules/chained_pool/eina_chained_mempool.c @@ -0,0 +1,201 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_inlist.h" +#include "eina_error.h" + +#include "eina_private.h" + +typedef struct _Chained_Mempool Chained_Mempool; +struct _Chained_Mempool +{ + Eina_Inlist *first; + const char *name; + int item_size; + int pool_size; + int usage; +}; + +typedef struct _Chained_Pool Chained_Pool; +struct _Chained_Pool +{ + Eina_Inlist _list_data; + void *base; + int usage; +}; + +static Chained_Pool * +_eina_chained_mp_pool_new(Chained_Mempool *pool) +{ + Chained_Pool *p; + void **ptr; + int item_alloc, i; + + item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *); + p = malloc(sizeof(Chained_Pool) + (pool->pool_size * item_alloc)); + ptr = (void **)(((unsigned char *)p) + sizeof(Chained_Pool)); + p->usage = 0; + p->base = ptr; + for (i = 0; i < pool->pool_size - 1; i++) + { + *ptr = (void **)(((unsigned char *)ptr) + item_alloc); + ptr = *ptr; + } + *ptr = NULL; + return p; +} + +static void +_eina_chained_mp_pool_free(Chained_Pool *p) +{ + free(p); +} + +static void * +eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size) +{ + Chained_Mempool *pool = data; + Chained_Pool *p; + Eina_Inlist *item; + void *mem; + + // look 4 pool from 2nd bucket on + EINA_INLIST_ITER_NEXT(pool->first, item) + { + p = (Chained_Pool*) item; + + // base is not NULL - has a free slot + if (p->base) + { + pool->first = eina_inlist_remove(pool->first, item); + break; + } + } + // we have reached the end of the list - no free pools + if (!p) + { + p = _eina_chained_mp_pool_new(pool); + if (!p) return NULL; + pool->first = eina_inlist_prepend(pool->first, p); + } + // this points to the next free block - so take it + mem = p->base; + // base now points to the next free block + p->base = *((void **)mem); + // move to end - it just filled up + if (!p->base) + { + pool->first = eina_inlist_remove(pool->first, p); + pool->first = eina_inlist_append(pool->first, p); + } + p->usage++; + pool->usage++; + return mem; +} + +static void +eina_chained_mempool_free(void *data, void *ptr) +{ + Chained_Mempool *pool = data; + Chained_Pool *p; + Eina_Inlist *item; + void *pmem; + int item_alloc, psize; + + item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *); + psize = item_alloc * pool->pool_size; + // look 4 pool + EINA_INLIST_ITER_NEXT(pool->first, item) + { + p = (Chained_Pool*) item; + + // pool mem base + pmem = (void *)(((unsigned char *)p) + sizeof(Chained_Pool)); + // is it in pool mem? + if ((ptr >= pmem) && ((unsigned char *)ptr < (((unsigned char *)pmem) + psize))) + { + // freed node points to prev free node + *((void **)ptr) = p->base; + // next free node is now the one we freed + p->base = ptr; + p->usage--; + pool->usage--; + pool->first = eina_inlist_remove(pool->first, p); + if (p->usage == 0) + // free bucket + _eina_chained_mp_pool_free(p); + else + // move to front + pool->first = eina_inlist_prepend(pool->first, p); + break; + } + } +} + +static void* +eina_chained_mempool_realloc(__UNUSED__ void *data, __UNUSED__ void *element, __UNUSED__ unsigned int size) +{ + return NULL; +} + +static void* +eina_chained_mempool_init(const char *context, __UNUSED__ const char *option, va_list args) +{ + Chained_Mempool *mp; + int length; + + length = context ? strlen(context) + 1 : 0; + + mp = calloc(1, sizeof(Chained_Mempool) + length); + if (!mp) return NULL; + + mp->item_size = va_arg(args, int); + mp->pool_size = va_arg(args, int); + + if (length) + { + mp->name = (const char*) (mp + 1); + memcpy((char*) mp->name, context, length); + } + + return mp; +} + +static void +eina_chained_mempool_shutdown(void *data) +{ + Chained_Mempool *mp; + + mp = (Chained_Mempool *) data; + + while (mp->first) + { + Chained_Pool *p = (Chained_Pool *) mp->first; + +#ifdef DEBUG + if (p->usage > 0) + EINA_ERROR_PINFO("Bad news we are destroying not an empty mempool [%s]\n", mp->name); +#endif + + mp->first = eina_inlist_remove(mp->first, mp->first); + _eina_chained_mp_pool_free(p); + } + + free(mp); +} + +Eina_Mempool_Backend mp_backend = { + .init = &eina_chained_mempool_init, + .shutdown = &eina_chained_mempool_shutdown, + .realloc = &eina_chained_mempool_realloc, + .alloc = &eina_chained_mempool_malloc, + .free = &eina_chained_mempool_free +}; -- 2.7.4