2 * Two Levels Segregate Fit memory allocator (TLSF)
5 * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
7 * Thanks to Ismael Ripoll for his suggestions and reviews
9 * Copyright (C) 2008, 2007, 2006, 2005, 2004
11 * This code is released using a dual license strategy: GPL/LGPL
12 * You can choose the licence that better fits your requirements.
14 * Released under the terms of the GNU General Public License Version 2.0
15 * Released under the terms of the GNU Lesser General Public License Version 2.1
22 * (Jul 28 2007) Herman ten Brugge <hermantenbrugge@home.nl>:
24 * - Add 64 bit support. It now runs on x86_64 and solaris64.
25 * - I also tested this on vxworks/32and solaris/32 and i386/32 processors.
26 * - Remove assembly code. I could not measure any performance difference
27 * on my core2 processor. This also makes the code more portable.
28 * - Moved defines/typedefs from tlsf.h to tlsf.c
29 * - Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to
30 * (sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact
31 * that the minumum size is still sizeof
33 * - Changed all C++ comment style to C style. (// -> /.* ... *./)
34 * - Used ls_bit instead of ffs and ms_bit instead of fls. I did this to
35 * avoid confusion with the standard ffs function which returns
37 * - Created set_bit/clear_bit fuctions because they are not present
39 * - Added locking support + extra file target.h to show how to use it.
40 * - Added get_used_size function (REMOVED in 2.4)
41 * - Added rtl_realloc and rtl_calloc function
42 * - Implemented realloc clever support.
43 * - Added some test code in the example directory.
46 * (Oct 23 2006) Adam Scislowicz:
48 * - Support for ARMv5 implemented
52 /*#define USE_SBRK (0) */
53 /*#define USE_MMAP (0) */
58 #ifndef TLSF_USE_LOCKS
59 #define TLSF_USE_LOCKS (0)
62 #ifndef TLSF_STATISTIC
63 #define TLSF_STATISTIC (0)
78 #define TLSF_CREATE_LOCK(_unused_) do{}while(0)
79 #define TLSF_DESTROY_LOCK(_unused_) do{}while(0)
80 #define TLSF_ACQUIRE_LOCK(_unused_) do{}while(0)
81 #define TLSF_RELEASE_LOCK(_unused_) do{}while(0)
85 #define TLSF_ADD_SIZE(tlsf, b) do { \
86 tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
87 if (tlsf->used_size > tlsf->max_size) \
88 tlsf->max_size = tlsf->used_size; \
91 #define TLSF_REMOVE_SIZE(tlsf, b) do { \
92 tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
95 #define TLSF_ADD_SIZE(tlsf, b) do{}while(0)
96 #define TLSF_REMOVE_SIZE(tlsf, b) do{}while(0)
99 #if USE_MMAP || USE_SBRK
104 #include <sys/mman.h>
109 #if !defined(__GNUC__)
115 /* The debug functions only can be used when _DEBUG_TLSF_ is set. */
117 #define _DEBUG_TLSF_ (0)
120 /*************************************************************************/
121 /* Definition of the structures used by TLSF */
124 /* Some IMPORTANT TLSF parameters */
125 /* Unlike the preview TLSF versions, now they are statics */
126 #define BLOCK_ALIGN (sizeof(void *) * 2)
129 #define MAX_LOG2_SLI (5)
130 #define MAX_SLI (1 << MAX_LOG2_SLI) /* MAX_SLI = 2^MAX_LOG2_SLI */
132 #define FLI_OFFSET (6) /* tlsf structure just will manage blocks bigger */
134 #define SMALL_BLOCK (128)
135 #define REAL_FLI (MAX_FLI - FLI_OFFSET)
136 #define MIN_BLOCK_SIZE (sizeof (free_ptr_t))
137 #define BHDR_OVERHEAD (sizeof (bhdr_t) - MIN_BLOCK_SIZE)
138 #define TLSF_SIGNATURE (0x2A59FA59)
140 #define PTR_MASK (sizeof(void *) - 1)
141 #define BLOCK_SIZE (0xFFFFFFFF - PTR_MASK)
143 #define GET_NEXT_BLOCK(_addr, _r) ((bhdr_t *) ((char *) (_addr) + (_r)))
144 #define MEM_ALIGN ((BLOCK_ALIGN) - 1)
145 #define ROUNDUP_SIZE(_r) (((_r) + MEM_ALIGN) & ~MEM_ALIGN)
146 #define ROUNDDOWN_SIZE(_r) ((_r) & ~MEM_ALIGN)
147 #define ROUNDUP(_x, _v) ((((~(_x)) + 1) & ((_v)-1)) + (_x))
149 #define BLOCK_STATE (0x1)
150 #define PREV_STATE (0x2)
152 /* bit 0 of the block size */
153 #define FREE_BLOCK (0x1)
154 #define USED_BLOCK (0x0)
156 /* bit 1 of the block size */
157 #define PREV_FREE (0x2)
158 #define PREV_USED (0x0)
161 #define DEFAULT_AREA_SIZE (1024*10)
164 #define PAGE_SIZE (getpagesize())
167 #define PRINT_MSG(fmt, args...) printf(fmt, ## args)
168 #define ERROR_MSG(fmt, args...) printf(fmt, ## args)
170 typedef unsigned int u32_t; /* NOTE: Make sure that this type is 4 bytes long on your computer */
171 typedef unsigned char u8_t; /* NOTE: Make sure that this type is 1 byte on your computer */
173 typedef struct free_ptr_struct {
174 struct bhdr_struct *prev;
175 struct bhdr_struct *next;
178 typedef struct bhdr_struct {
179 /* This pointer is just valid if the first bit of size is set */
180 struct bhdr_struct *prev_hdr;
181 /* The size is stored in bytes */
182 size_t size; /* bit 0 indicates whether the block is used and */
183 /* bit 1 allows to know whether the previous block is free */
185 struct free_ptr_struct free_ptr;
186 u8_t buffer[1]; /*sizeof(struct free_ptr_struct)]; */
190 /* This structure is embedded at the beginning of each area, giving us
191 * enough information to cope with a set of areas */
193 typedef struct area_info_struct {
195 struct area_info_struct *next;
198 typedef struct TLSF_struct {
199 /* the TLSF's structure signature */
200 u32_t tlsf_signature;
207 /* These can not be calculated outside tlsf because we
208 * do not know the sizes when freeing/reallocing memory. */
213 /* A linked list holding all the existing areas */
214 area_info_t *area_head;
216 /* the first-level bitmap */
217 /* This array should have a size of REAL_FLI bits */
220 /* the second-level bitmap */
221 u32_t sl_bitmap[REAL_FLI];
223 bhdr_t *matrix[REAL_FLI][MAX_SLI];
227 /******************************************************************/
228 /************** Helping functions **************************/
229 /******************************************************************/
230 static __inline__ void set_bit(int nr, u32_t * addr);
231 static __inline__ void clear_bit(int nr, u32_t * addr);
232 static __inline__ int ls_bit(int x);
233 static __inline__ int ms_bit(int x);
234 static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl);
235 static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl);
236 static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl);
237 static __inline__ bhdr_t *process_area(void *area, size_t size);
238 #if USE_SBRK || USE_MMAP
239 static __inline__ void *get_new_area(size_t * size);
242 static const int table[] = {
243 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
246 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
252 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
255 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
258 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
261 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
264 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
269 static __inline__ int ls_bit(int i)
272 unsigned int x = i & -i;
274 a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
275 return table[x >> a] + a;
278 static __inline__ int ms_bit(int i)
281 unsigned int x = (unsigned int) i;
283 a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
284 return table[x >> a] + a;
287 static __inline__ void set_bit(int nr, u32_t * addr)
289 addr[nr >> 5] |= 1 << (nr & 0x1f);
292 static __inline__ void clear_bit(int nr, u32_t * addr)
294 addr[nr >> 5] &= ~(1 << (nr & 0x1f));
297 static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl)
301 if (*_r < SMALL_BLOCK) {
303 *_sl = *_r / (SMALL_BLOCK / MAX_SLI);
305 _t = (1 << (ms_bit(*_r) - MAX_LOG2_SLI)) - 1;
308 *_sl = (*_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
310 /*if ((*_fl -= FLI_OFFSET) < 0) // FL wil be always >0!
317 static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl)
319 if (_r < SMALL_BLOCK) {
321 *_sl = _r / (SMALL_BLOCK / MAX_SLI);
324 *_sl = (_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
330 static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl)
332 u32_t _tmp = _tlsf->sl_bitmap[*_fl] & (~0 << *_sl);
337 _b = _tlsf->matrix[*_fl][*_sl];
339 *_fl = ls_bit(_tlsf->fl_bitmap & (~0 << (*_fl + 1)));
340 if (*_fl > 0) { /* likely */
341 *_sl = ls_bit(_tlsf->sl_bitmap[*_fl]);
342 _b = _tlsf->matrix[*_fl][*_sl];
349 #define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) do { \
350 _tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next; \
351 if (_tlsf -> matrix[_fl][_sl]) \
352 _tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL; \
354 clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \
355 if (!_tlsf -> sl_bitmap [_fl]) \
356 clear_bit (_fl, &_tlsf -> fl_bitmap); \
358 _b -> ptr.free_ptr.prev = NULL; \
359 _b -> ptr.free_ptr.next = NULL; \
363 #define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) do { \
364 if (_b -> ptr.free_ptr.next) \
365 _b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \
366 if (_b -> ptr.free_ptr.prev) \
367 _b -> ptr.free_ptr.prev -> ptr.free_ptr.next = _b -> ptr.free_ptr.next; \
368 if (_tlsf -> matrix [_fl][_sl] == _b) { \
369 _tlsf -> matrix [_fl][_sl] = _b -> ptr.free_ptr.next; \
370 if (!_tlsf -> matrix [_fl][_sl]) { \
371 clear_bit (_sl, &_tlsf -> sl_bitmap[_fl]); \
372 if (!_tlsf -> sl_bitmap [_fl]) \
373 clear_bit (_fl, &_tlsf -> fl_bitmap); \
376 _b -> ptr.free_ptr.prev = NULL; \
377 _b -> ptr.free_ptr.next = NULL; \
380 #define INSERT_BLOCK(_b, _tlsf, _fl, _sl) do { \
381 _b -> ptr.free_ptr.prev = NULL; \
382 _b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \
383 if (_tlsf -> matrix [_fl][_sl]) \
384 _tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b; \
385 _tlsf -> matrix [_fl][_sl] = _b; \
386 set_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \
387 set_bit (_fl, &_tlsf -> fl_bitmap); \
390 #if USE_SBRK || USE_MMAP
391 static __inline__ void *get_new_area(size_t * size)
396 area = (void *)sbrk(0);
397 if (((void *)sbrk(*size)) != ((void *) -1))
402 *size = ROUNDUP(*size, PAGE_SIZE);
403 if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED)
406 return ((void *) ~0);
410 static __inline__ bhdr_t *process_area(void *area, size_t size)
415 ib = (bhdr_t *) area;
417 (sizeof(area_info_t) <
418 MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED;
419 b = (bhdr_t *) GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
420 b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED;
421 b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0;
422 lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
424 lb->size = 0 | USED_BLOCK | PREV_FREE;
425 ai = (area_info_t *) ib->ptr.buffer;
431 /******************************************************************/
432 /******************** Begin of the allocator code *****************/
433 /******************************************************************/
435 static char *mp = NULL; /* Default memory pool. */
437 /******************************************************************/
438 size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
440 /******************************************************************/
444 if (!mem_pool || !mem_pool_size || mem_pool_size < sizeof(tlsf_t) + BHDR_OVERHEAD * 8) {
445 ERROR_MSG("init_memory_pool (): memory_pool invalid\n");
449 if (((unsigned long) mem_pool & PTR_MASK)) {
450 ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n");
453 tlsf = (tlsf_t *) mem_pool;
454 /* Check if already initialised */
455 if (tlsf->tlsf_signature == TLSF_SIGNATURE) {
457 b = GET_NEXT_BLOCK(mp, ROUNDUP_SIZE(sizeof(tlsf_t)));
458 return b->size & BLOCK_SIZE;
463 /* Zeroing the memory pool */
464 memset(mem_pool, 0, sizeof(tlsf_t));
466 tlsf->tlsf_signature = TLSF_SIGNATURE;
468 TLSF_CREATE_LOCK(&tlsf->lock);
470 ib = process_area(GET_NEXT_BLOCK
471 (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));
472 b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
473 free_ex(b->ptr.buffer, tlsf);
474 tlsf->area_head = (area_info_t *) ib->ptr.buffer;
477 tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE);
478 tlsf->max_size = tlsf->used_size;
481 return (b->size & BLOCK_SIZE);
484 /******************************************************************/
485 size_t add_new_area(void *area, size_t area_size, void *mem_pool)
487 /******************************************************************/
488 tlsf_t *tlsf = (tlsf_t *) mem_pool;
489 area_info_t *ptr, *ptr_prev, *ai;
490 bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b;
492 memset(area, 0, area_size);
493 ptr = tlsf->area_head;
496 ib0 = process_area(area, area_size);
497 b0 = GET_NEXT_BLOCK(ib0->ptr.buffer, ib0->size & BLOCK_SIZE);
498 lb0 = GET_NEXT_BLOCK(b0->ptr.buffer, b0->size & BLOCK_SIZE);
500 /* Before inserting the new area, we have to merge this area with the
501 already existing ones */
504 ib1 = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
505 b1 = GET_NEXT_BLOCK(ib1->ptr.buffer, ib1->size & BLOCK_SIZE);
508 /* Merging the new area with the next physically contigous one */
509 if ((unsigned long) ib1 == (unsigned long) lb0 + BHDR_OVERHEAD) {
510 if (tlsf->area_head == ptr) {
511 tlsf->area_head = ptr->next;
514 ptr_prev->next = ptr->next;
519 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
520 (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED;
528 /* Merging the new area with the previous physically contigous
530 if ((unsigned long) lb1->ptr.buffer == (unsigned long) ib0) {
531 if (tlsf->area_head == ptr) {
532 tlsf->area_head = ptr->next;
535 ptr_prev->next = ptr->next;
540 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
541 (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE);
542 next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE);
543 next_b->prev_hdr = lb1;
553 /* Inserting the area in the list of linked areas */
554 ai = (area_info_t *) ib0->ptr.buffer;
555 ai->next = tlsf->area_head;
557 tlsf->area_head = ai;
558 free_ex(b0->ptr.buffer, mem_pool);
559 return (b0->size & BLOCK_SIZE);
563 /******************************************************************/
564 size_t get_used_size(void *mem_pool)
566 /******************************************************************/
568 return ((tlsf_t *) mem_pool)->used_size;
574 /******************************************************************/
575 size_t get_max_size(void *mem_pool)
577 /******************************************************************/
579 return ((tlsf_t *) mem_pool)->max_size;
585 /******************************************************************/
586 void destroy_memory_pool(void *mem_pool)
588 /******************************************************************/
589 tlsf_t *tlsf = (tlsf_t *) mem_pool;
591 tlsf->tlsf_signature = 0;
593 TLSF_DESTROY_LOCK(&tlsf->lock);
598 /******************************************************************/
599 void *tlsf_malloc(size_t size)
601 /******************************************************************/
604 #if USE_MMAP || USE_SBRK
609 area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8; /* Just a safety constant */
610 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
611 area = get_new_area(&area_size);
612 if (area == ((void *) ~0))
613 return NULL; /* Not enough system memory */
614 init_memory_pool(area_size, area);
618 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
620 ret = malloc_ex(size, mp);
622 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
627 /******************************************************************/
628 void tlsf_free(void *ptr)
630 /******************************************************************/
632 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
636 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
640 /******************************************************************/
641 void *tlsf_realloc(void *ptr, size_t size)
643 /******************************************************************/
646 #if USE_MMAP || USE_SBRK
648 return tlsf_malloc(size);
652 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
654 ret = realloc_ex(ptr, size, mp);
656 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
661 /******************************************************************/
662 void *tlsf_calloc(size_t nelem, size_t elem_size)
664 /******************************************************************/
667 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
669 ret = calloc_ex(nelem, elem_size, mp);
671 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
676 /******************************************************************/
677 void *malloc_ex(size_t size, void *mem_pool)
679 /******************************************************************/
680 tlsf_t *tlsf = (tlsf_t *) mem_pool;
681 bhdr_t *b, *b2, *next_b;
685 size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size);
687 /* Rounding up the requested size and calculating fl and sl */
688 MAPPING_SEARCH(&size, &fl, &sl);
690 /* Searching a free block, recall that this function changes the values of fl and sl,
691 so they are not longer valid when the function fails */
692 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
693 #if USE_MMAP || USE_SBRK
697 /* Growing the pool size when needed */
698 area_size = size + BHDR_OVERHEAD * 8; /* size plus enough room for the requered headers. */
699 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
700 area = get_new_area(&area_size); /* Call sbrk or mmap */
701 if (area == ((void *) ~0))
702 return NULL; /* Not enough system memory */
703 add_new_area(area, area_size, mem_pool);
704 /* Rounding up the requested size and calculating fl and sl */
705 MAPPING_SEARCH(&size, &fl, &sl);
706 /* Searching a free block */
707 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
711 return NULL; /* Not found */
713 EXTRACT_BLOCK_HDR(b, tlsf, fl, sl);
716 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
717 /* Should the block be split? */
718 tmp_size = (b->size & BLOCK_SIZE) - size;
719 if (tmp_size >= sizeof(bhdr_t)) {
720 tmp_size -= BHDR_OVERHEAD;
721 b2 = GET_NEXT_BLOCK(b->ptr.buffer, size);
722 b2->size = tmp_size | FREE_BLOCK | PREV_USED;
723 next_b->prev_hdr = b2;
724 MAPPING_INSERT(tmp_size, &fl, &sl);
725 INSERT_BLOCK(b2, tlsf, fl, sl);
727 b->size = size | (b->size & PREV_STATE);
729 next_b->size &= (~PREV_FREE);
730 b->size &= (~FREE_BLOCK); /* Now it's used */
733 TLSF_ADD_SIZE(tlsf, b);
735 return (void *) b->ptr.buffer;
738 /******************************************************************/
739 void free_ex(void *ptr, void *mem_pool)
741 /******************************************************************/
742 tlsf_t *tlsf = (tlsf_t *) mem_pool;
749 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
750 b->size |= FREE_BLOCK;
752 TLSF_REMOVE_SIZE(tlsf, b);
754 b->ptr.free_ptr.prev = NULL;
755 b->ptr.free_ptr.next = NULL;
756 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
757 if (tmp_b->size & FREE_BLOCK) {
758 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
759 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
760 b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
762 if (b->size & PREV_FREE) {
764 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
765 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
766 tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
769 MAPPING_INSERT(b->size & BLOCK_SIZE, &fl, &sl);
770 INSERT_BLOCK(b, tlsf, fl, sl);
772 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
773 tmp_b->size |= PREV_FREE;
777 /******************************************************************/
778 void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
780 /******************************************************************/
781 tlsf_t *tlsf = (tlsf_t *) mem_pool;
784 bhdr_t *b, *tmp_b, *next_b;
790 return (void *) malloc_ex(new_size, mem_pool);
793 } else if (!new_size) {
794 free_ex(ptr, mem_pool);
798 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
799 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
800 new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size);
801 tmp_size = (b->size & BLOCK_SIZE);
802 if (new_size <= tmp_size) {
803 TLSF_REMOVE_SIZE(tlsf, b);
804 if (next_b->size & FREE_BLOCK) {
805 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
806 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
807 tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
808 next_b = GET_NEXT_BLOCK(next_b->ptr.buffer, next_b->size & BLOCK_SIZE);
809 /* We allways reenter this free block because tmp_size will
810 be greater then sizeof (bhdr_t) */
812 tmp_size -= new_size;
813 if (tmp_size >= sizeof(bhdr_t)) {
814 tmp_size -= BHDR_OVERHEAD;
815 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
816 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
817 next_b->prev_hdr = tmp_b;
818 next_b->size |= PREV_FREE;
819 MAPPING_INSERT(tmp_size, &fl, &sl);
820 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
821 b->size = new_size | (b->size & PREV_STATE);
823 TLSF_ADD_SIZE(tlsf, b);
824 return (void *) b->ptr.buffer;
826 if ((next_b->size & FREE_BLOCK)) {
827 if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) {
828 TLSF_REMOVE_SIZE(tlsf, b);
829 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
830 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
831 b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
832 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
833 next_b->prev_hdr = b;
834 next_b->size &= ~PREV_FREE;
835 tmp_size = (b->size & BLOCK_SIZE) - new_size;
836 if (tmp_size >= sizeof(bhdr_t)) {
837 tmp_size -= BHDR_OVERHEAD;
838 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
839 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
840 next_b->prev_hdr = tmp_b;
841 next_b->size |= PREV_FREE;
842 MAPPING_INSERT(tmp_size, &fl, &sl);
843 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
844 b->size = new_size | (b->size & PREV_STATE);
846 TLSF_ADD_SIZE(tlsf, b);
847 return (void *) b->ptr.buffer;
851 ptr_aux = malloc_ex(new_size, mem_pool);
853 cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE);
855 memcpy(ptr_aux, ptr, cpsize);
857 free_ex(ptr, mem_pool);
862 /******************************************************************/
863 void *calloc_ex(size_t nelem, size_t elem_size, void *mem_pool)
865 /******************************************************************/
868 if (nelem <= 0 || elem_size <= 0)
871 if (!(ptr = malloc_ex(nelem * elem_size, mem_pool)))
873 memset(ptr, 0, nelem * elem_size);
882 /*************** DEBUG FUNCTIONS **************/
884 /* The following functions have been designed to ease the debugging of */
885 /* the TLSF structure. For non-developing purposes, it may be they */
886 /* haven't too much worth. To enable them, _DEBUG_TLSF_ must be set. */
888 extern void dump_memory_region(unsigned char *mem_ptr, unsigned int size);
889 extern void print_block(bhdr_t * b);
890 extern void print_tlsf(tlsf_t * tlsf);
891 void print_all_blocks(tlsf_t * tlsf);
893 void dump_memory_region(unsigned char *mem_ptr, unsigned int size)
896 unsigned long begin = (unsigned long) mem_ptr;
897 unsigned long end = (unsigned long) mem_ptr + size;
907 PRINT_MSG("\nMemory region dumped: 0x%lx - 0x%lx\n\n", begin, end);
910 PRINT_MSG("0x%lx ", begin);
912 while (begin < end) {
913 if (((unsigned char *) begin)[0] == 0)
916 PRINT_MSG("%02x", ((unsigned char *) begin)[0]);
917 if (((unsigned char *) begin)[1] == 0)
920 PRINT_MSG("%02x ", ((unsigned char *) begin)[1]);
924 PRINT_MSG("\n0x%lx ", begin);
932 void print_block(bhdr_t * b)
936 PRINT_MSG(">> [%p] (", b);
937 if ((b->size & BLOCK_SIZE))
938 PRINT_MSG("%lu bytes, ", (unsigned long) (b->size & BLOCK_SIZE));
940 PRINT_MSG("sentinel, ");
941 if ((b->size & BLOCK_STATE) == FREE_BLOCK)
942 PRINT_MSG("free [%p, %p], ", b->ptr.free_ptr.prev, b->ptr.free_ptr.next);
945 if ((b->size & PREV_STATE) == PREV_FREE)
946 PRINT_MSG("prev. free [%p])\n", b->prev_hdr);
948 PRINT_MSG("prev used)\n");
951 void print_tlsf(tlsf_t * tlsf)
956 PRINT_MSG("\nTLSF at %p\n", tlsf);
958 PRINT_MSG("FL bitmap: 0x%x\n\n", (unsigned) tlsf->fl_bitmap);
960 for (i = 0; i < REAL_FLI; i++) {
961 if (tlsf->sl_bitmap[i])
962 PRINT_MSG("SL bitmap 0x%x\n", (unsigned) tlsf->sl_bitmap[i]);
963 for (j = 0; j < MAX_SLI; j++) {
964 next = tlsf->matrix[i][j];
966 PRINT_MSG("-> [%d][%d]\n", i, j);
969 next = next->ptr.free_ptr.next;
975 void print_all_blocks(tlsf_t * tlsf)
979 PRINT_MSG("\nTLSF at %p\nALL BLOCKS\n\n", tlsf);
980 ai = tlsf->area_head;
982 next = (bhdr_t *) ((char *) ai - BHDR_OVERHEAD);
985 if ((next->size & BLOCK_SIZE))
986 next = GET_NEXT_BLOCK(next->ptr.buffer, next->size & BLOCK_SIZE);