1 /* EINA - EFL data type library
2 * Copyright (C) 2010 Cedric BAIL, Vincent Torri
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
26 #ifdef EFL_HAVE_POSIX_THREADS
32 #ifdef EFL_HAVE_WIN32_THREADS
33 # define WIN32_LEAN_AND_MEAN
35 # undef WIN32_LEAN_AND_MEAN
38 #include "eina_mempool.h"
39 #include "eina_trash.h"
40 #include "eina_inlist.h"
42 #include "eina_lock.h"
45 # include <memcheck.h>
48 #include "eina_private.h"
53 #define INF(...) EINA_LOG_DOM_INFO(_eina_mempool_log_dom, __VA_ARGS__)
58 #define WRN(...) EINA_LOG_DOM_WARN(_eina_one_big_mp_log_dom, __VA_ARGS__)
60 static int _eina_one_big_mp_log_dom = -1;
62 typedef struct _One_Big One_Big;
77 Eina_Inlist *over_list;
79 #ifdef EFL_DEBUG_THREADS
86 eina_one_big_malloc(void *data, __UNUSED__ unsigned int size)
89 unsigned char *mem = NULL;
91 if (!eina_lock_take(&pool->mutex))
93 #ifdef EFL_DEBUG_THREADS
94 assert(pthread_equal(pool->self, pthread_self()));
101 VALGRIND_MAKE_MEM_DEFINED(pool->empty, pool->item_size);
103 mem = eina_trash_pop(&pool->empty);
110 pool->base = malloc(pool->item_size * pool->max);
113 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
117 VALGRIND_MAKE_MEM_NOACCESS(pool->base, pool->item_size * pool->max);
121 if (pool->served < pool->max)
123 mem = pool->base + (pool->served++ *pool->item_size);
130 mem = malloc(sizeof(Eina_Inlist) + pool->item_size);
132 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
136 memset(mem, 0, sizeof(Eina_Inlist));
137 pool->over_list = eina_inlist_append(pool->over_list,
139 mem = ((unsigned char *)mem) + sizeof(Eina_Inlist);
142 VALGRIND_MAKE_MEM_NOACCESS(mem, pool->item_size);
146 eina_lock_release(&pool->mutex);
149 VALGRIND_MEMPOOL_ALLOC(pool, mem, pool->item_size);
155 eina_one_big_free(void *data, void *ptr)
157 One_Big *pool = data;
159 if (!eina_lock_take(&pool->mutex))
161 #ifdef EFL_DEBUG_THREADS
162 assert(pthread_equal(pool->self, pthread_self()));
166 if ((void *)pool->base <= ptr
167 && ptr < (void *)(pool->base + (pool->max * pool->item_size)))
169 eina_trash_push(&pool->empty, ptr);
179 il = (Eina_Inlist *)(((unsigned char *)ptr) - sizeof(Eina_Inlist));
182 for (it = pool->over_list; it != NULL; it = it->next)
188 pool->over_list = eina_inlist_remove(pool->over_list, il);
194 VALGRIND_MEMPOOL_FREE(pool, ptr);
197 eina_lock_release(&pool->mutex);
201 eina_one_big_realloc(__UNUSED__ void *data,
202 __UNUSED__ void *element,
203 __UNUSED__ unsigned int size)
209 eina_one_big_init(const char *context,
210 __UNUSED__ const char *option,
217 length = context ? strlen(context) + 1 : 0;
219 pool = calloc(1, sizeof (One_Big) + length);
223 item_size = va_arg(args, int);
225 pool->item_size = eina_mempool_alignof(item_size);
226 pool->max = va_arg(args, int);
230 pool->name = (const char *)(pool + 1);
231 memcpy((char *)pool->name, context, length);
234 #ifdef EFL_DEBUG_THREADS
235 pool->self = pthread_self();
237 eina_lock_new(&pool->mutex);
240 VALGRIND_CREATE_MEMPOOL(pool, 0, 1);
247 eina_one_big_shutdown(void *data)
249 One_Big *pool = data;
252 if (!eina_lock_take(&pool->mutex))
254 #ifdef EFL_DEBUG_THREADS
255 assert(pthread_equal(pool->self, pthread_self()));
261 // FIXME: should we warn here? one_big mempool exceeded its alloc and now
262 // mempool is cleaning up the mess created. be quiet for now as we were before
263 // but edje seems to be a big offender at the moment! bad cedric! :)
265 // "Pool [%s] over by %i. cleaning up for you",
266 // pool->name, pool->over);
267 while (pool->over_list)
269 Eina_Inlist *il = pool->over_list;
270 pool->over_list = eina_inlist_remove(pool->over_list, il);
278 "Pool [%s] still over by %i\n",
279 pool->name, pool->over);
283 VALGRIND_DESTROY_MEMPOOL(pool);
286 if (pool->base) free(pool->base);
288 eina_lock_release(&pool->mutex);
289 eina_lock_free(&pool->mutex);
294 static Eina_Mempool_Backend _eina_one_big_mp_backend = {
298 &eina_one_big_malloc,
299 &eina_one_big_realloc,
302 &eina_one_big_shutdown,
306 Eina_Bool one_big_init(void)
309 _eina_one_big_mp_log_dom = eina_log_domain_register("eina_one_big_mempool",
310 EINA_LOG_COLOR_DEFAULT);
311 if (_eina_one_big_mp_log_dom < 0)
313 EINA_LOG_ERR("Could not register log domain: eina_one_big_mempool");
318 return eina_mempool_register(&_eina_one_big_mp_backend);
321 void one_big_shutdown(void)
323 eina_mempool_unregister(&_eina_one_big_mp_backend);
325 eina_log_domain_unregister(_eina_one_big_mp_log_dom);
326 _eina_one_big_mp_log_dom = -1;
330 #ifndef EINA_STATIC_BUILD_ONE_BIG
332 EINA_MODULE_INIT(one_big_init);
333 EINA_MODULE_SHUTDOWN(one_big_shutdown);
335 #endif /* ! EINA_STATIC_BUILD_ONE_BIG */