summaryrefslogtreecommitdiff
path: root/legacy/evas/src/lib/main.c
diff options
context:
space:
mode:
authorCarsten Haitzler <raster@rasterman.com>2005-11-25 08:29:39 +0000
committerCarsten Haitzler <raster@rasterman.com>2005-11-25 08:29:39 +0000
commit20bad98318c9f1864f1ad10fb4c08c68bdc1f9b8 (patch)
treeecc384e42cce6fcac8f17d46a702a31461a0b8dc /legacy/evas/src/lib/main.c
parent7278f1d18bc300e665ac0e44b99dc82293304404 (diff)
new - much cleaner/simpler mempool
SVN revision: 18642
Diffstat (limited to '')
-rw-r--r--legacy/evas/src/lib/main.c458
1 files changed, 93 insertions, 365 deletions
diff --git a/legacy/evas/src/lib/main.c b/legacy/evas/src/lib/main.c
index 758c513c71..711b41f39c 100644
--- a/legacy/evas/src/lib/main.c
+++ b/legacy/evas/src/lib/main.c
@@ -208,303 +208,51 @@ evas_debug_magic_string_get(DATA32 magic)
208 return "<UNKNOWN>"; 208 return "<UNKNOWN>";
209} 209}
210 210
211typedef struct _Evas_Mempool1 Evas_Mempool1;
212typedef struct _Evas_Mempool2 Evas_Mempool2;
213typedef unsigned int Evas_Mempool_Bitmask;
214 211
215struct _Evas_Mempool1 /* used if pool size <= 32 */
216{
217 Evas_Mempool_Bitmask allocated;
218 Evas_Mempool1 *next;
219 unsigned char *mem;
220};
221 212
222struct _Evas_Mempool2 /* used if pool size > 32 */
223{
224 Evas_Mempool_Bitmask allocated, filled;
225 Evas_Mempool_Bitmask allocated_list[32];
226 Evas_Mempool2 *next;
227 unsigned char *mem;
228};
229 213
230static Evas_Mempool1 *
231_evas_mempoool1_new(Evas_Mempool *pool)
232{
233 Evas_Mempool1 *mp;
234
235 if (pool->pool_size <= 32)
236 mp = malloc(sizeof(Evas_Mempool1) + (pool->item_size * pool->pool_size));
237 else
238 mp = malloc(sizeof(Evas_Mempool1) + (pool->item_size * 32));
239 mp->allocated = 0;
240 mp->next = NULL;
241 mp->mem = (unsigned char *)mp + sizeof(Evas_Mempool1);
242 return mp;
243}
244 214
245static void
246_evas_mempool1_free(Evas_Mempool1 *mp)
247{
248 free(mp);
249}
250 215
251static Evas_Mempool1 *
252_evas_mempool1_free_find(Evas_Mempool *pool, int *slot, Evas_Mempool1 **pmp)
253{
254 Evas_Mempool1 *mp;
255 int i, psize;
256 Evas_Mempool_Bitmask allocated;
257
258 psize = pool->pool_size;
259 if (psize > 32) psize = 32;
260 for (mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next)
261 {
262 allocated = mp->allocated;
263 if (allocated != 0xffffffff)
264 {
265 for (i = 0; i < psize; i++)
266 {
267 if ((allocated & (1 << i)) == 0)
268 {
269 *slot = i;
270 return mp;
271 }
272 }
273 }
274 *pmp = mp;
275 if (!mp->next) mp->next = _evas_mempoool1_new(pool);
276 }
277 return NULL;
278}
279 216
280static Evas_Mempool1 *
281_evas_mempool1_pointer_find(Evas_Mempool *pool, int *slot, Evas_Mempool1 **pmp, unsigned char *ptr)
282{
283 Evas_Mempool1 *mp;
284 int i, psize, isize;
285 unsigned char *mem;
286
287 psize = pool->pool_size;
288 if (psize > 32) psize = 32;
289 isize = pool->item_size;
290 for (mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next)
291 {
292 mem = mp->mem;
293 if (ptr >= mem)
294 {
295 i = (ptr - mem) / isize;
296 if (i < psize)
297 {
298 *slot = i;
299 return mp;
300 }
301 }
302 *pmp = mp;
303 }
304 return NULL;
305}
306 217
307static void
308_evas_mempool1_slot_set(Evas_Mempool1 *mp, int slot)
309{
310 mp->allocated |= (1 << slot);
311}
312 218
313static void 219typedef struct _Pool Pool;
314_evas_mempool1_slot_unset(Evas_Mempool1 *mp, int slot)
315{
316 mp->allocated &= ~(1 << slot);
317}
318 220
319/* 221struct _Pool
320static void
321_evas_mempool1_debug(Evas_Mempool *pool)
322{ 222{
323 Evas_Mempool1 *mp; 223 int usage;
324 int psize, isize, i, j, bits, space, allocated, nodes; 224 void *base;
325 225 Pool *prev, *next;
326 psize = pool->pool_size; 226};
327 if (psize > 32) psize = 32;
328 isize = pool->item_size;
329 nodes = allocated = space = 0;
330 for (i = 0, mp = (Evas_Mempool1 *)pool->first; mp; mp = mp->next, i++)
331 {
332 bits = 0;
333
334 for (j = 0; j < 32; j++)
335 {
336 if ((mp->allocated & (1 << j)) != 0) bits++;
337 }
338 allocated += bits * isize;
339 space += psize * isize;
340 nodes++;
341// printf("pool %i, alloc %08x, full %i/%i\n",
342// i, mp->allocated, bits, 32);
343 }
344 printf("pool[0-32] %p usage (%i @ %i, %i nodes) %3.1f%%\n",
345 pool, pool->usage, psize, nodes,
346 100.0 * (double)allocated / (double)space);
347}
348*/
349
350
351
352static Evas_Mempool2 *
353_evas_mempoool2_new(Evas_Mempool *pool)
354{
355 Evas_Mempool2 *mp;
356
357 if (pool->pool_size <= 1024)
358 mp = malloc(sizeof(Evas_Mempool2) + (pool->item_size * pool->pool_size));
359 else
360 mp = malloc(sizeof(Evas_Mempool2) + (pool->item_size * 1024));
361 mp->allocated = 0;
362 mp->filled = 0;
363 memset(mp->allocated_list, 0, sizeof(int) * 32);
364 mp->next = NULL;
365 mp->mem = (unsigned char *)mp + sizeof(Evas_Mempool2);
366 return mp;
367}
368
369static void
370_evas_mempool2_free(Evas_Mempool2 *mp)
371{
372 free(mp);
373}
374
375static Evas_Mempool2 *
376_evas_mempool2_free_find(Evas_Mempool *pool, int *slot, Evas_Mempool2 **pmp)
377{
378 Evas_Mempool2 *mp;
379 int i, j, psize, ps, bsize;
380 Evas_Mempool_Bitmask allocated, filled;
381
382 psize = pool->pool_size;
383 if (psize > 1024) psize = 1024;
384 bsize = (psize + 31) / 32;
385 for (mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next)
386 {
387 filled = mp->filled;
388 if (filled != 0xffffffff)
389 {
390 for (j = 0; j < bsize; j++)
391 {
392 if ((filled & (1 << j)) == 0)
393 {
394 if (j == bsize - 1)
395 ps = psize - (j * 32);
396 else
397 ps = 32;
398 allocated = mp->allocated_list[j];
399 for (i = 0; i < ps; i++)
400 {
401 if ((allocated & (1 << i)) == 0)
402 {
403 *slot = (j * 32) + i;
404 return mp;
405 }
406 }
407 }
408 }
409 }
410 *pmp = mp;
411 if (!mp->next) mp->next = _evas_mempoool2_new(pool);
412 }
413 return NULL;
414}
415 227
416static Evas_Mempool2 * 228Pool *
417_evas_mempool2_pointer_find(Evas_Mempool *pool, int *slot, Evas_Mempool2 **pmp, unsigned char *ptr) 229_evas_mp_pool_new(Evas_Mempool *pool)
418{ 230{
419 Evas_Mempool2 *mp; 231 Pool *p;
420 int i, psize, isize; 232 void **ptr;
421 unsigned char *mem; 233 int item_alloc, i;
422 234
423 psize = pool->pool_size; 235 item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
424 if (psize > 1024) psize = 1024; 236 p = malloc(sizeof(Pool) + (pool->pool_size * item_alloc));
425 isize = pool->item_size; 237 ptr = (void **)(((unsigned char *)p) + sizeof(Pool));
426 for (mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next) 238 p->usage = 0;
239 p->base = ptr;
240 for (i = 0; i < pool->pool_size - 1; i++)
427 { 241 {
428 mem = mp->mem; 242 *ptr = (void **)(((unsigned char *)ptr) + item_alloc);
429 if (ptr >= mem) 243 ptr = *ptr;
430 {
431 i = (ptr - mem) / isize;
432 if (i < psize)
433 {
434 *slot = i;
435 return mp;
436 }
437 }
438 *pmp = mp;
439 } 244 }
440 return NULL; 245 *ptr = NULL;
246 return p;
441} 247}
442 248
443static void 249void
444_evas_mempool2_slot_set(Evas_Mempool2 *mp, int slot) 250_evas_mp_pool_free(Pool *p)
445{
446 int bucket;
447
448 bucket = slot / 32;
449 mp->allocated_list[bucket] |= (1 << (slot - (bucket * 32)));
450 mp->allocated |= (1 << bucket);
451 if (mp->allocated_list[bucket] == 0xffffffff)
452 mp->filled |= (1 << bucket);
453}
454
455static void
456_evas_mempool2_slot_unset(Evas_Mempool2 *mp, int slot)
457{ 251{
458 int bucket; 252 free(p);
459
460 bucket = slot / 32;
461 mp->allocated_list[bucket] &= ~(1 << (slot - (bucket * 32)));
462 mp->filled &= ~(1 << bucket);
463 if (mp->allocated_list[bucket] == 0)
464 mp->allocated &= ~(1 << bucket);
465} 253}
466 254
467/* 255//#define NOPOOL
468static void
469_evas_mempool2_debug(Evas_Mempool *pool)
470{
471 Evas_Mempool2 *mp;
472 int psize, bsize, isize, i, j, ps, bits, allocated, space, nodes;
473
474 psize = pool->pool_size;
475 if (psize > 1024) psize = 1024;
476 bsize = (psize + 31) / 32;
477 isize = pool->item_size;
478 nodes = allocated = space = 0;
479 for (i = 0, mp = (Evas_Mempool2 *)pool->first; mp; mp = mp->next, i++)
480 {
481 for (i = 0; i < bsize; i++)
482 {
483 bits = 0;
484 if (i == bsize - 1)
485 ps = psize - (i * 32);
486 else
487 ps = 32;
488 for (j = 0; j < ps; j++)
489 {
490 if ((mp->allocated_list[i] & (1 << j)) != 0) bits++;
491 }
492// printf("pool %i, alloc %08x, full %i/%i\n",
493// i, mp->allocated, bits, 32);
494 allocated += bits * isize;
495 }
496 space += psize * isize;
497 nodes++;
498 }
499 printf("pool[32-1024] %p usage (%i @ %i, %i nodes) %3.1f%%\n",
500 pool, pool->usage, psize, nodes,
501 100.0 * (double)allocated / (double)space);
502}
503*/
504
505/* disabled for now - it seems a little bit slower than glibc */
506#define NOPOOL 1
507
508void * 256void *
509evas_mempool_malloc(Evas_Mempool *pool, int size) 257evas_mempool_malloc(Evas_Mempool *pool, int size)
510#ifdef NOPOOL 258#ifdef NOPOOL
@@ -513,62 +261,53 @@ evas_mempool_malloc(Evas_Mempool *pool, int size)
513} 261}
514#else 262#else
515{ 263{
516 if (pool->pool_size <= 32) 264 Pool *p;
265 void *mem;
266
267 for (p = pool->first; p; p = p->next) // look 4 pool from 2nd bucket on
517 { 268 {
518 Evas_Mempool1 *mp, *pmp = NULL; 269 if (p->base) // base is not NULL - has a free slot
519 int freeslot;
520
521 mp = pool->first;
522 if (!mp)
523 {
524 mp = _evas_mempoool1_new(pool);
525 pool->first = mp;
526 freeslot = 0;
527 }
528 else mp = _evas_mempool1_free_find(pool, &freeslot, &pmp);
529 if (!mp) return NULL;
530 pool->usage++;
531 _evas_mempool1_slot_set(mp, freeslot);
532 if (mp->allocated == 0xffffffff)
533 { 270 {
534 if (mp->next) 271 if (p->prev)
535 { 272 {
536 if (pool->first == mp) pool->first = mp->next; 273 if (pool->last == p) pool->last = p->prev;
537 else pmp->next = mp; 274 p->prev->next = p->next;
538 mp->next = NULL; 275 p->prev = NULL;
276 p->next = pool->first;
277 p->next->prev = p;
278 pool->first = p;
539 } 279 }
280 break;
540 } 281 }
541/* _evas_mempool1_debug(pool);*/
542 return mp->mem + (freeslot * pool->item_size);
543 } 282 }
544 else 283 if (!p) // we have reached the end of the list - no free pools
545 { 284 {
546 Evas_Mempool2 *mp, *pmp = NULL; 285 p = _evas_mp_pool_new(pool);
547 int freeslot; 286 if (!p) return NULL;
548 287 p->prev = NULL;
549 mp = pool->first; 288 p->next = pool->first;
550 if (!mp) 289 if (p->next) p->next->prev = p;
551 { 290 if (!pool->last) pool->last = p;
552 mp = _evas_mempoool2_new(pool); 291 pool->first = p;
553 pool->first = mp; 292 }
554 freeslot = 0; 293 mem = p->base; // this points to the next free block - so take it
555 } 294 p->base = *((void **)mem); // base now points to the next free block
556 else mp = _evas_mempool2_free_find(pool, &freeslot, &pmp); 295 if (!p->base) // move to end - it just filled up
557 if (!mp) return NULL; 296 {
558 pool->usage++; 297 if (p->next)
559 _evas_mempool2_slot_set(mp, freeslot);
560 if (mp->allocated == 0xffffffff)
561 { 298 {
562 if (mp->next) 299 if (p->prev) p->prev->next = p->next;
563 { 300 else pool->first = p->next;
564 if (pool->first == mp) pool->first = mp->next; 301 p->next->prev = p->prev;
565 else pmp->next = mp; 302 ((Pool *)pool->last)->next = p;
566 mp->next = NULL; 303 p->prev = pool->last;
567 } 304 p->next = NULL;
305 pool->last = p;
568 } 306 }
569/* _evas_mempool2_debug(pool);*/
570 return mp->mem + (freeslot * pool->item_size);
571 } 307 }
308 p->usage++;
309 pool->usage++;
310 return mem;
572} 311}
573#endif 312#endif
574 313
@@ -580,55 +319,44 @@ evas_mempool_free(Evas_Mempool *pool, void *ptr)
580} 319}
581#else 320#else
582{ 321{
583 if (pool->pool_size <= 32) 322 Pool *p;
323 void *pmem;
324 int item_alloc, psize;
325
326 item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
327 psize = item_alloc * pool->pool_size;
328 for (p = (Pool *)(pool->first); p; p = p->next) // look 4 pool
584 { 329 {
585 Evas_Mempool1 *mp, *pmp = NULL; 330 pmem = (void *)(((unsigned char *)p) + sizeof(Pool)); // pool mem base
586 int allocslot; 331 if ((ptr >= pmem) && (ptr < (pmem + psize))) // is it in pool mem?
587
588 mp = _evas_mempool1_pointer_find(pool, &allocslot, &pmp, (unsigned char*)ptr);
589 if (!mp) return;
590 _evas_mempool1_slot_unset(mp, allocslot);
591 if (mp->allocated == 0)
592 {
593 if (pool->first == mp) pool->first = mp->next;
594 else pmp->next = mp->next;
595 _evas_mempool1_free(mp);
596 }
597 else
598 { 332 {
599 if (pool->first != mp) 333 *((void **)ptr) = p->base; // freed node points to prev free node
334 p->base = ptr; // next free node is now the one we freed
335 p->usage--;
336 pool->usage--;
337 if (p->usage == 0) // free bucket
600 { 338 {
601 pmp->next = mp->next; 339 if (p->prev) p->prev->next = p->next;
602 mp->next = pool->first; 340 if (p->next) p->next->prev = p->prev;
603 pool->first = mp; 341 if (pool->last == p) pool->last = p->prev;
342 if (pool->first == p) pool->first = p->next;
343 _evas_mp_pool_free(p);
604 } 344 }
605 } 345 else
606 pool->usage--;
607 }
608 else
609 {
610 Evas_Mempool2 *mp, *pmp = NULL;
611 int allocslot;
612
613 mp = _evas_mempool2_pointer_find(pool, &allocslot, &pmp, (unsigned char*)ptr);
614 if (!mp) return;
615 _evas_mempool2_slot_unset(mp, allocslot);
616 if (mp->allocated == 0)
617 {
618 if (pool->first == mp) pool->first = mp->next;
619 else pmp->next = mp->next;
620 _evas_mempool2_free(mp);
621 }
622 else
623 {
624 if (pool->first != mp)
625 { 346 {
626 pmp->next = mp->next; 347 if (p->prev) // if not the first - move to front
627 mp->next = pool->first; 348 {
628 pool->first = mp; 349 p->prev->next = p->next;
350 if (p->next) p->next->prev = p->prev;
351 if (pool->last == p) pool->last = p->prev;
352 p->prev = NULL;
353 p->next = pool->first;
354 p->next->prev = p;
355 pool->first = p;
356 }
629 } 357 }
358 break;
630 } 359 }
631 pool->usage--;
632 } 360 }
633} 361}
634#endif 362#endif