summaryrefslogtreecommitdiff
path: root/lib/tlsf/src/tlsf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tlsf/src/tlsf.c')
-rw-r--r--lib/tlsf/src/tlsf.c295
1 files changed, 194 insertions, 101 deletions
diff --git a/lib/tlsf/src/tlsf.c b/lib/tlsf/src/tlsf.c
index 46ae7616b1..15fa8002d2 100644
--- a/lib/tlsf/src/tlsf.c
+++ b/lib/tlsf/src/tlsf.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Two Levels Segregate Fit memory allocator (TLSF) 2 * Two Levels Segregate Fit memory allocator (TLSF)
3 * Version 2.4.4 3 * Version 2.4.6
4 * 4 *
5 * Written by Miguel Masmano Tello <mimastel@doctor.upv.es> 5 * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
6 * 6 *
@@ -23,27 +23,27 @@
23 * 23 *
24 * - Add 64 bit support. It now runs on x86_64 and solaris64. 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. 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 26 * - Remove assembly code. I could not measure any performance difference
27 * on my core2 processor. This also makes the code more portable. 27 * on my core2 processor. This also makes the code more portable.
28 * - Moved defines/typedefs from tlsf.h to tlsf.c 28 * - Moved defines/typedefs from tlsf.h to tlsf.c
29 * - Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to 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 30 * (sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact
31 * that the minumum size is still sizeof 31 * that the minumum size is still sizeof
32 * (bhdr_t). 32 * (bhdr_t).
33 * - Changed all C++ comment style to C style. (// -> /.* ... *./) 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 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 35 * avoid confusion with the standard ffs function which returns
36 * different values. 36 * different values.
37 * - Created set_bit/clear_bit fuctions because they are not present 37 * - Created set_bit/clear_bit fuctions because they are not present
38 * on x86_64. 38 * on x86_64.
39 * - Added locking support + extra file target.h to show how to use it. 39 * - Added locking support + extra file target.h to show how to use it.
40 * - Added get_used_size function (REMOVED in 2.4) 40 * - Added get_used_size function (REMOVED in 2.4)
41 * - Added rtl_realloc and rtl_calloc function 41 * - Added rtl_realloc and rtl_calloc function
42 * - Implemented realloc clever support. 42 * - Implemented realloc clever support.
43 * - Added some test code in the example directory. 43 * - Added some test code in the example directory.
44 * 44 * - Bug fixed (discovered by the rockbox project: www.rockbox.org).
45 * 45 *
46 * (Oct 23 2006) Adam Scislowicz: 46 * (Oct 23 2006) Adam Scislowicz:
47 * 47 *
48 * - Support for ARMv5 implemented 48 * - Support for ARMv5 implemented
49 * 49 *
@@ -52,10 +52,32 @@
52/*#define USE_SBRK (0) */ 52/*#define USE_SBRK (0) */
53/*#define USE_MMAP (0) */ 53/*#define USE_MMAP (0) */
54 54
55#ifdef HAVE_CONFIG_H
56#include "config.h"
57#endif //HAVE_CONFIG_H
58
59#ifdef HAVE_STDIO_H
55#include <stdio.h> 60#include <stdio.h>
56#include <string.h> 61#endif
62
57#include <stdint.h> 63#include <stdint.h>
58 64
65void abort(void);
66
67#if defined(ROCKBOX) && (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(DEBUG)
68#define USE_PRINTF 1
69#endif
70
71#if defined(ROCKBOX)
72#include "panic.h"
73#endif
74
75#ifndef USE_PRINTF
76#define USE_PRINTF (0)
77#endif
78
79#include <string.h>
80
59#ifndef TLSF_USE_LOCKS 81#ifndef TLSF_USE_LOCKS
60#define TLSF_USE_LOCKS (0) 82#define TLSF_USE_LOCKS (0)
61#endif 83#endif
@@ -65,11 +87,11 @@
65#endif 87#endif
66 88
67#ifndef USE_MMAP 89#ifndef USE_MMAP
68#define USE_MMAP (0) 90#define USE_MMAP (0)
69#endif 91#endif
70 92
71#ifndef USE_SBRK 93#ifndef USE_SBRK
72#define USE_SBRK (0) 94#define USE_SBRK (0)
73#endif 95#endif
74 96
75 97
@@ -77,20 +99,22 @@
77#include "target.h" 99#include "target.h"
78#else 100#else
79#define TLSF_CREATE_LOCK(_unused_) do{}while(0) 101#define TLSF_CREATE_LOCK(_unused_) do{}while(0)
80#define TLSF_DESTROY_LOCK(_unused_) do{}while(0) 102#define TLSF_DESTROY_LOCK(_unused_) do{}while(0)
81#define TLSF_ACQUIRE_LOCK(_unused_) do{}while(0) 103#define TLSF_ACQUIRE_LOCK(_unused_) do{}while(0)
82#define TLSF_RELEASE_LOCK(_unused_) do{}while(0) 104#define TLSF_RELEASE_LOCK(_unused_) do{}while(0)
83#endif 105#endif
84 106
85#if TLSF_STATISTIC 107#if TLSF_STATISTIC
86#define TLSF_ADD_SIZE(tlsf, b) do { \ 108#define TLSF_ADD_SIZE(tlsf, b) \
87 tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \ 109 do { \
88 if (tlsf->used_size > tlsf->max_size) \ 110 tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
89 tlsf->max_size = tlsf->used_size; \ 111 if (tlsf->used_size > tlsf->max_size) \
90 } while(0) 112 tlsf->max_size = tlsf->used_size; \
91 113 } while(0)
92#define TLSF_REMOVE_SIZE(tlsf, b) do { \ 114
93 tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \ 115#define TLSF_REMOVE_SIZE(tlsf, b) \
116 do { \
117 tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
94 } while(0) 118 } while(0)
95#else 119#else
96#define TLSF_ADD_SIZE(tlsf, b) do{}while(0) 120#define TLSF_ADD_SIZE(tlsf, b) do{}while(0)
@@ -105,7 +129,6 @@
105#include <sys/mman.h> 129#include <sys/mman.h>
106#endif 130#endif
107 131
108#include "config.h"
109#include "tlsf.h" 132#include "tlsf.h"
110 133
111#if !defined(__GNUC__) 134#if !defined(__GNUC__)
@@ -127,37 +150,49 @@
127/* Unlike the preview TLSF versions, now they are statics */ 150/* Unlike the preview TLSF versions, now they are statics */
128#define BLOCK_ALIGN (sizeof(void *) * 2) 151#define BLOCK_ALIGN (sizeof(void *) * 2)
129 152
130#define MAX_FLI (30) 153#define MAX_FLI (30)
131#define MAX_LOG2_SLI (5) 154#define MAX_LOG2_SLI (5)
132#define MAX_SLI (1 << MAX_LOG2_SLI) /* MAX_SLI = 2^MAX_LOG2_SLI */ 155#define MAX_SLI (1 << MAX_LOG2_SLI) /* MAX_SLI = 2^MAX_LOG2_SLI */
133 156
134#define FLI_OFFSET (6) /* tlsf structure just will manage blocks bigger */ 157#define FLI_OFFSET (6) /* tlsf structure just will manage blocks bigger */
135/* than 128 bytes */ 158/* than 128 bytes */
136#define SMALL_BLOCK (128) 159#define SMALL_BLOCK (128)
137#define REAL_FLI (MAX_FLI - FLI_OFFSET) 160#define REAL_FLI (MAX_FLI - FLI_OFFSET)
138#define MIN_BLOCK_SIZE (sizeof (free_ptr_t)) 161#define MIN_BLOCK_SIZE (sizeof (free_ptr_t))
139#define BHDR_OVERHEAD (sizeof (bhdr_t) - MIN_BLOCK_SIZE) 162#define BHDR_OVERHEAD (sizeof (bhdr_t) - MIN_BLOCK_SIZE)
140#define TLSF_SIGNATURE (0x2A59FA59) 163#define TLSF_SIGNATURE (0x2A59FA59)
141 164
142#define PTR_MASK (sizeof(void *) - 1) 165#define PTR_MASK (sizeof(void *) - 1)
143#define BLOCK_SIZE (0xFFFFFFFF - PTR_MASK) 166#define BLOCK_SIZE (0xFFFFFFFF - PTR_MASK)
167
144 168
145#define GET_NEXT_BLOCK(_addr, _r) ((bhdr_t *) ((char *) (_addr) + (_r))) 169/* Dereferencing type-punned pointers will break strict aliasing.*/
146#define MEM_ALIGN ((BLOCK_ALIGN) - 1) 170#ifdef __GNUC__
171/* GCC guarantees that casting through a union is valid. */
172#define TYPE_PUN(dsttype, srctype, x) \
173 (((union {srctype *a; dsttype *b;})(x)).b)
174#else
175#define TYPE_PUN(dsttype, srctype, x) ( (dsttype*)(x) )
176#endif /* __GNUC__ */
177
178#define GET_NEXT_BLOCK(_addr, _r) TYPE_PUN(bhdr_t, char, (char *) (_addr) + (_r))
179
180#define MEM_ALIGN ((BLOCK_ALIGN) - 1)
147#define ROUNDUP_SIZE(_r) (((_r) + MEM_ALIGN) & ~MEM_ALIGN) 181#define ROUNDUP_SIZE(_r) (((_r) + MEM_ALIGN) & ~MEM_ALIGN)
148#define ROUNDDOWN_SIZE(_r) ((_r) & ~MEM_ALIGN) 182#define ROUNDDOWN_SIZE(_r) ((_r) & ~MEM_ALIGN)
149#define ROUNDUP(_x, _v) ((((~(_x)) + 1) & ((_v)-1)) + (_x)) 183#define ROUNDUP(_x, _v) ((((~(_x)) + 1) & ((_v)-1)) + (_x))
150 184
151#define BLOCK_STATE (0x1) 185#define BLOCK_STATE (0x1)
152#define PREV_STATE (0x2) 186#define PREV_STATE (0x2)
187#define STATE_MASK (BLOCK_STATE | PREV_STATE)
153 188
154/* bit 0 of the block size */ 189/* bit 0 of the block size */
155#define FREE_BLOCK (0x1) 190#define FREE_BLOCK (0x1)
156#define USED_BLOCK (0x0) 191#define USED_BLOCK (0x0)
157 192
158/* bit 1 of the block size */ 193/* bit 1 of the block size */
159#define PREV_FREE (0x2) 194#define PREV_FREE (0x2)
160#define PREV_USED (0x0) 195#define PREV_USED (0x0)
161 196
162 197
163#define DEFAULT_AREA_SIZE (1024*10) 198#define DEFAULT_AREA_SIZE (1024*10)
@@ -166,14 +201,17 @@
166#define PAGE_SIZE (getpagesize()) 201#define PAGE_SIZE (getpagesize())
167#endif 202#endif
168 203
169#if defined(ROCKBOX) && (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(DEBUG) \ 204#if USE_PRINTF
170 || !defined(ROCKBOX) 205#include <stdio.h>
171int printf(const char* fmt, ...); 206# define PRINT_MSG(fmt, args...) printf(fmt, ## args)
172#define PRINT_MSG(fmt, args...) printf(fmt, ## args) 207# define ERROR_MSG(fmt, args...) printf(fmt, ## args)
173#define ERROR_MSG(fmt, args...) printf(fmt, ## args)
174#else 208#else
175#define PRINT_MSG(fmt, args...) 209# if !defined(PRINT_MSG)
176#define ERROR_MSG(fmt, args...) 210# define PRINT_MSG(fmt, args...)
211# endif
212# if !defined(ERROR_MSG)
213# define ERROR_MSG(fmt, args...)
214# endif
177#endif 215#endif
178 216
179typedef unsigned int u32_t; /* NOTE: Make sure that this type is 4 bytes long on your computer */ 217typedef unsigned int u32_t; /* NOTE: Make sure that this type is 4 bytes long on your computer */
@@ -236,6 +274,7 @@ typedef struct TLSF_struct {
236/******************************************************************/ 274/******************************************************************/
237/************** Helping functions **************************/ 275/************** Helping functions **************************/
238/******************************************************************/ 276/******************************************************************/
277static __inline__ void corrupt(const char *s);
239static __inline__ void set_bit(int nr, u32_t * addr); 278static __inline__ void set_bit(int nr, u32_t * addr);
240static __inline__ void clear_bit(int nr, u32_t * addr); 279static __inline__ void clear_bit(int nr, u32_t * addr);
241static __inline__ int ls_bit(int x); 280static __inline__ int ls_bit(int x);
@@ -248,6 +287,14 @@ static __inline__ bhdr_t *process_area(void *area, size_t size);
248static __inline__ void *get_new_area(size_t * size); 287static __inline__ void *get_new_area(size_t * size);
249#endif 288#endif
250 289
290#if defined(ROCKBOX)
291void *get_new_area(size_t * size);
292#endif
293
294static __inline__ bhdr_t *encode_prev_block( bhdr_t *prev, size_t size ) {
295 return (bhdr_t*) ( ((intptr_t)prev | STATE_MASK) & ~(size & STATE_MASK) );
296}
297
251static const int table[] = { 298static const int table[] = {
252 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 299 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
253 4, 4, 300 4, 4,
@@ -354,22 +401,43 @@ static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl
354 return _b; 401 return _b;
355} 402}
356 403
404#if defined(ROCKBOX)
405static __inline__ void corrupt(const char *msg) {
406 panicf("* Heap Corruption: %s", msg);
407}
408
409void __attribute__((weak)) panicf( const char *fmt, ... )
410{
411 /* Do nothing */
412 (void)fmt;
413 do { } while (1);
414}
415#else
416static __inline__ void corrupt(const char *msg) {
417 static const char *k = "* Heap corruption detected: *\n";
418 write( STDERR_FILENO, k, strlen(k) );
419 write( STDERR_FILENO, msg, strlen(msg) );
420 abort();
421}
422#endif
357 423
358#define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) do { \ 424#define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) \
359 _tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next; \ 425 do { \
360 if (_tlsf -> matrix[_fl][_sl]) \ 426 _tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next; \
361 _tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL; \ 427 if (_tlsf -> matrix[_fl][_sl]) \
362 else { \ 428 _tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL; \
363 clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \ 429 else { \
364 if (!_tlsf -> sl_bitmap [_fl]) \ 430 clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \
365 clear_bit (_fl, &_tlsf -> fl_bitmap); \ 431 if (!_tlsf -> sl_bitmap [_fl]) \
366 } \ 432 clear_bit (_fl, &_tlsf -> fl_bitmap); \
367 _b -> ptr.free_ptr.prev = NULL; \ 433 } \
368 _b -> ptr.free_ptr.next = NULL; \ 434 _b -> ptr.free_ptr.prev = NULL; \
435 _b -> ptr.free_ptr.next = NULL; \
369 }while(0) 436 }while(0)
370 437
371 438
372#define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) do { \ 439#define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) \
440 do { \
373 if (_b -> ptr.free_ptr.next) \ 441 if (_b -> ptr.free_ptr.next) \
374 _b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \ 442 _b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \
375 if (_b -> ptr.free_ptr.prev) \ 443 if (_b -> ptr.free_ptr.prev) \
@@ -382,13 +450,14 @@ static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl
382 clear_bit (_fl, &_tlsf -> fl_bitmap); \ 450 clear_bit (_fl, &_tlsf -> fl_bitmap); \
383 } \ 451 } \
384 } \ 452 } \
385 _b -> ptr.free_ptr.prev = NULL; \ 453 _b -> ptr.free_ptr.prev = NULL; \
386 _b -> ptr.free_ptr.next = NULL; \ 454 _b -> ptr.free_ptr.next = NULL; \
387 } while(0) 455 } while(0)
388 456
389#define INSERT_BLOCK(_b, _tlsf, _fl, _sl) do { \ 457#define INSERT_BLOCK(_b, _tlsf, _fl, _sl) \
390 _b -> ptr.free_ptr.prev = NULL; \ 458 do { \
391 _b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \ 459 _b -> ptr.free_ptr.prev = NULL; \
460 _b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \
392 if (_tlsf -> matrix [_fl][_sl]) \ 461 if (_tlsf -> matrix [_fl][_sl]) \
393 _tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b; \ 462 _tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b; \
394 _tlsf -> matrix [_fl][_sl] = _b; \ 463 _tlsf -> matrix [_fl][_sl] = _b; \
@@ -405,7 +474,7 @@ void * __attribute__((weak)) get_new_area(size_t * size)
405#endif 474#endif
406 475
407#if USE_SBRK || USE_MMAP 476#if USE_SBRK || USE_MMAP
408static __inline__ void *get_new_area(size_t * size) 477static __inline__ void *get_new_area(size_t * size)
409{ 478{
410 void *area; 479 void *area;
411 480
@@ -415,12 +484,18 @@ static __inline__ void *get_new_area(size_t * size)
415 return area; 484 return area;
416#endif 485#endif
417 486
487#ifndef MAP_ANONYMOUS
488/* https://dev.openwrt.org/ticket/322 */
489# define MAP_ANONYMOUS MAP_ANON
490#endif
491
492
418#if USE_MMAP 493#if USE_MMAP
419 *size = ROUNDUP(*size, PAGE_SIZE); 494 *size = ROUNDUP(*size, PAGE_SIZE);
420 if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) 495 if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED)
421 return area; 496 return area;
422#endif 497#endif
423 return ((void *) ~0); 498 return ((void *) ~0u);
424} 499}
425#endif 500#endif
426 501
@@ -433,13 +508,15 @@ static __inline__ bhdr_t *process_area(void *area, size_t size)
433 ib->size = 508 ib->size =
434 (sizeof(area_info_t) < 509 (sizeof(area_info_t) <
435 MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED; 510 MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED;
436 b = (bhdr_t *) GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE); 511 ib->prev_hdr = encode_prev_block( NULL, ib->size );
512 b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
437 b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED; 513 b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED;
514 b->prev_hdr = encode_prev_block( NULL, b->size );
438 b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0; 515 b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0;
439 lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE); 516 lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
440 lb->prev_hdr = b;
441 lb->size = 0 | USED_BLOCK | PREV_FREE; 517 lb->size = 0 | USED_BLOCK | PREV_FREE;
442 ai = (area_info_t *) ib->ptr.buffer; 518 lb->prev_hdr = encode_prev_block( b, lb->size );
519 ai = TYPE_PUN(area_info_t, u8_t, ib->ptr.buffer);
443 ai->next = 0; 520 ai->next = 0;
444 ai->end = lb; 521 ai->end = lb;
445 return ib; 522 return ib;
@@ -463,7 +540,7 @@ size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
463 return -1; 540 return -1;
464 } 541 }
465 542
466 if (((intptr_t) mem_pool & PTR_MASK)) { 543 if (((unsigned long) mem_pool & PTR_MASK)) {
467 ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n"); 544 ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n");
468 return -1; 545 return -1;
469 } 546 }
@@ -488,7 +565,7 @@ size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
488 (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t))); 565 (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));
489 b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE); 566 b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
490 free_ex(b->ptr.buffer, tlsf); 567 free_ex(b->ptr.buffer, tlsf);
491 tlsf->area_head = (area_info_t *) ib->ptr.buffer; 568 tlsf->area_head = TYPE_PUN(area_info_t, u8_t, ib->ptr.buffer);
492 569
493#if TLSF_STATISTIC 570#if TLSF_STATISTIC
494 tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE); 571 tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE);
@@ -506,9 +583,6 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
506 area_info_t *ptr, *ptr_prev, *ai; 583 area_info_t *ptr, *ptr_prev, *ai;
507 bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b; 584 bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b;
508 585
509 /* FW 28-10-17: disabled memset due to crashes on ARM. Functions
510 * fine without it. */
511 /* BILGUS 17-7-19 re-enabled after setting pluginbuf aligned to 8 bytes */
512 memset(area, 0, area_size); 586 memset(area, 0, area_size);
513 ptr = tlsf->area_head; 587 ptr = tlsf->area_head;
514 ptr_prev = 0; 588 ptr_prev = 0;
@@ -526,7 +600,7 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
526 lb1 = ptr->end; 600 lb1 = ptr->end;
527 601
528 /* Merging the new area with the next physically contigous one */ 602 /* Merging the new area with the next physically contigous one */
529 if ((uintptr_t) ib1 == (uintptr_t) lb0 + BHDR_OVERHEAD) { 603 if ((unsigned long) ib1 == (unsigned long) lb0 + BHDR_OVERHEAD) {
530 if (tlsf->area_head == ptr) { 604 if (tlsf->area_head == ptr) {
531 tlsf->area_head = ptr->next; 605 tlsf->area_head = ptr->next;
532 ptr = ptr->next; 606 ptr = ptr->next;
@@ -539,7 +613,7 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
539 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) + 613 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
540 (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED; 614 (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED;
541 615
542 b1->prev_hdr = b0; 616 b1->prev_hdr = encode_prev_block( b0, b0->size );
543 lb0 = lb1; 617 lb0 = lb1;
544 618
545 continue; 619 continue;
@@ -547,7 +621,7 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
547 621
548 /* Merging the new area with the previous physically contigous 622 /* Merging the new area with the previous physically contigous
549 one */ 623 one */
550 if ((intptr_t) lb1->ptr.buffer == (intptr_t) ib0) { 624 if ((unsigned long) lb1->ptr.buffer == (unsigned long) ib0) {
551 if (tlsf->area_head == ptr) { 625 if (tlsf->area_head == ptr) {
552 tlsf->area_head = ptr->next; 626 tlsf->area_head = ptr->next;
553 ptr = ptr->next; 627 ptr = ptr->next;
@@ -560,7 +634,7 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
560 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) + 634 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
561 (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE); 635 (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE);
562 next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE); 636 next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE);
563 next_b->prev_hdr = lb1; 637 next_b->prev_hdr = encode_prev_block( lb1, next_b->size );
564 b0 = lb1; 638 b0 = lb1;
565 ib0 = ib1; 639 ib0 = ib1;
566 640
@@ -571,7 +645,7 @@ size_t add_new_area(void *area, size_t area_size, void *mem_pool)
571 } 645 }
572 646
573 /* Inserting the area in the list of linked areas */ 647 /* Inserting the area in the list of linked areas */
574 ai = (area_info_t *) ib0->ptr.buffer; 648 ai = TYPE_PUN(area_info_t, u8_t, ib0->ptr.buffer);
575 ai->next = tlsf->area_head; 649 ai->next = tlsf->area_head;
576 ai->end = lb0; 650 ai->end = lb0;
577 tlsf->area_head = ai; 651 tlsf->area_head = ai;
@@ -587,9 +661,7 @@ size_t get_used_size(void *mem_pool)
587#if TLSF_STATISTIC 661#if TLSF_STATISTIC
588 return ((tlsf_t *) mem_pool)->used_size; 662 return ((tlsf_t *) mem_pool)->used_size;
589#else 663#else
590#ifdef ROCKBOX 664 (void)mem_pool;
591 (void) mem_pool;
592#endif /* ROCKBOX */
593 return 0; 665 return 0;
594#endif 666#endif
595} 667}
@@ -601,9 +673,7 @@ size_t get_max_size(void *mem_pool)
601#if TLSF_STATISTIC 673#if TLSF_STATISTIC
602 return ((tlsf_t *) mem_pool)->max_size; 674 return ((tlsf_t *) mem_pool)->max_size;
603#else 675#else
604#ifdef ROCKBOX 676 (void)mem_pool;
605 (void) mem_pool;
606#endif /* ROCKBOX */
607 return 0; 677 return 0;
608#endif 678#endif
609} 679}
@@ -635,7 +705,7 @@ void *tlsf_malloc(size_t size)
635 area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8; /* Just a safety constant */ 705 area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8; /* Just a safety constant */
636 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE; 706 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
637 area = get_new_area(&area_size); 707 area = get_new_area(&area_size);
638 if (area == ((void *) ~0)) 708 if (area == ((void *) ~0u))
639 return NULL; /* Not enough system memory */ 709 return NULL; /* Not enough system memory */
640 init_memory_pool(area_size, area); 710 init_memory_pool(area_size, area);
641 } 711 }
@@ -670,9 +740,9 @@ void *tlsf_realloc(void *ptr, size_t size)
670 void *ret; 740 void *ret;
671 741
672#if USE_MMAP || USE_SBRK || defined(ROCKBOX) 742#if USE_MMAP || USE_SBRK || defined(ROCKBOX)
673 if (!mp) { 743 if (!mp) {
674 return tlsf_malloc(size); 744 return tlsf_malloc(size);
675 } 745 }
676#endif 746#endif
677 747
678 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock); 748 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
@@ -716,7 +786,6 @@ void *malloc_ex(size_t size, void *mem_pool)
716 /* Searching a free block, recall that this function changes the values of fl and sl, 786 /* Searching a free block, recall that this function changes the values of fl and sl,
717 so they are not longer valid when the function fails */ 787 so they are not longer valid when the function fails */
718 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl); 788 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
719
720#if USE_MMAP || USE_SBRK || defined(ROCKBOX) 789#if USE_MMAP || USE_SBRK || defined(ROCKBOX)
721 if (!b) { 790 if (!b) {
722 size_t area_size; 791 size_t area_size;
@@ -725,7 +794,7 @@ void *malloc_ex(size_t size, void *mem_pool)
725 area_size = size + BHDR_OVERHEAD * 8; /* size plus enough room for the requered headers. */ 794 area_size = size + BHDR_OVERHEAD * 8; /* size plus enough room for the requered headers. */
726 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE; 795 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
727 area = get_new_area(&area_size); /* Call sbrk or mmap */ 796 area = get_new_area(&area_size); /* Call sbrk or mmap */
728 if (area == ((void *) ~0)) 797 if (area == ((void *) ~0u))
729 return NULL; /* Not enough system memory */ 798 return NULL; /* Not enough system memory */
730 add_new_area(area, area_size, mem_pool); 799 add_new_area(area, area_size, mem_pool);
731 /* Rounding up the requested size and calculating fl and sl */ 800 /* Rounding up the requested size and calculating fl and sl */
@@ -747,18 +816,24 @@ void *malloc_ex(size_t size, void *mem_pool)
747 tmp_size -= BHDR_OVERHEAD; 816 tmp_size -= BHDR_OVERHEAD;
748 b2 = GET_NEXT_BLOCK(b->ptr.buffer, size); 817 b2 = GET_NEXT_BLOCK(b->ptr.buffer, size);
749 b2->size = tmp_size | FREE_BLOCK | PREV_USED; 818 b2->size = tmp_size | FREE_BLOCK | PREV_USED;
750 next_b->prev_hdr = b2; 819 b2->prev_hdr = encode_prev_block( b2->prev_hdr, b2->size );
820 next_b->prev_hdr = encode_prev_block(b2, next_b->size);
751 MAPPING_INSERT(tmp_size, &fl, &sl); 821 MAPPING_INSERT(tmp_size, &fl, &sl);
752 INSERT_BLOCK(b2, tlsf, fl, sl); 822 INSERT_BLOCK(b2, tlsf, fl, sl);
753 823
754 b->size = size | (b->size & PREV_STATE); 824 b->size = size | (b->size & PREV_STATE);
755 } else { 825 } else {
756 next_b->size &= (~PREV_FREE); 826 next_b->size &= (~PREV_FREE);
827 next_b->prev_hdr = encode_prev_block( next_b->prev_hdr, next_b->size );
757 b->size &= (~FREE_BLOCK); /* Now it's used */ 828 b->size &= (~FREE_BLOCK); /* Now it's used */
758 } 829 }
830 b->prev_hdr = encode_prev_block( b->prev_hdr, b->size );
759 831
760 TLSF_ADD_SIZE(tlsf, b); 832 TLSF_ADD_SIZE(tlsf, b);
761 833
834 if( (b->size & BLOCK_STATE) != (~(intptr_t)b->prev_hdr & BLOCK_STATE) )
835 corrupt("malloc_ex(): Mismatched flags after allocation\n");
836
762 return (void *) b->ptr.buffer; 837 return (void *) b->ptr.buffer;
763} 838}
764 839
@@ -773,7 +848,14 @@ void free_ex(void *ptr, void *mem_pool)
773 if (!ptr) { 848 if (!ptr) {
774 return; 849 return;
775 } 850 }
851
776 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD); 852 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
853
854 if( (b->size & BLOCK_STATE) != USED_BLOCK )
855 corrupt( "free_ex(): Freeing unused block\n" );
856 if( (b->size & BLOCK_STATE) != (~(intptr_t)b->prev_hdr & BLOCK_STATE) )
857 corrupt("free_ex(): Mismatched flags\n");
858
777 b->size |= FREE_BLOCK; 859 b->size |= FREE_BLOCK;
778 860
779 TLSF_REMOVE_SIZE(tlsf, b); 861 TLSF_REMOVE_SIZE(tlsf, b);
@@ -782,12 +864,14 @@ void free_ex(void *ptr, void *mem_pool)
782 b->ptr.free_ptr.next = NULL; 864 b->ptr.free_ptr.next = NULL;
783 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE); 865 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
784 if (tmp_b->size & FREE_BLOCK) { 866 if (tmp_b->size & FREE_BLOCK) {
867 /* Coalesce next block */
785 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl); 868 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
786 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl); 869 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
787 b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD; 870 b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
788 } 871 }
789 if (b->size & PREV_FREE) { 872 if (b->size & PREV_FREE) {
790 tmp_b = b->prev_hdr; 873 /* Coalesce previous block */
874 tmp_b = (bhdr_t*) ( (intptr_t)b->prev_hdr & BLOCK_SIZE );
791 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl); 875 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
792 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl); 876 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
793 tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; 877 tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
@@ -797,8 +881,11 @@ void free_ex(void *ptr, void *mem_pool)
797 INSERT_BLOCK(b, tlsf, fl, sl); 881 INSERT_BLOCK(b, tlsf, fl, sl);
798 882
799 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE); 883 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
884 /* if tmp_b is free, it should have been coalesced */
885 if( (tmp_b->size & BLOCK_STATE) == FREE_BLOCK )
886 corrupt( "free_ex(): uncoalesced block\n");
800 tmp_b->size |= PREV_FREE; 887 tmp_b->size |= PREV_FREE;
801 tmp_b->prev_hdr = b; 888 tmp_b->prev_hdr = encode_prev_block(b, tmp_b->size);
802} 889}
803 890
804/******************************************************************/ 891/******************************************************************/
@@ -827,8 +914,10 @@ void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
827 new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size); 914 new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size);
828 tmp_size = (b->size & BLOCK_SIZE); 915 tmp_size = (b->size & BLOCK_SIZE);
829 if (new_size <= tmp_size) { 916 if (new_size <= tmp_size) {
830 TLSF_REMOVE_SIZE(tlsf, b); 917 /* shrink allocated portion */
918 TLSF_REMOVE_SIZE(tlsf, b);
831 if (next_b->size & FREE_BLOCK) { 919 if (next_b->size & FREE_BLOCK) {
920 /* coalesce next block (free) */
832 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl); 921 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
833 EXTRACT_BLOCK(next_b, tlsf, fl, sl); 922 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
834 tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD; 923 tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
@@ -838,45 +927,49 @@ void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
838 } 927 }
839 tmp_size -= new_size; 928 tmp_size -= new_size;
840 if (tmp_size >= sizeof(bhdr_t)) { 929 if (tmp_size >= sizeof(bhdr_t)) {
930 /* add tail as free block */
841 tmp_size -= BHDR_OVERHEAD; 931 tmp_size -= BHDR_OVERHEAD;
842 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size); 932 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
843 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED; 933 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
844 next_b->prev_hdr = tmp_b; 934 tmp_b->prev_hdr = encode_prev_block( NULL, tmp_b->size );
845 next_b->size |= PREV_FREE; 935 next_b->size |= PREV_FREE;
936 next_b->prev_hdr = encode_prev_block( tmp_b, next_b->size );
846 MAPPING_INSERT(tmp_size, &fl, &sl); 937 MAPPING_INSERT(tmp_size, &fl, &sl);
847 INSERT_BLOCK(tmp_b, tlsf, fl, sl); 938 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
848 b->size = new_size | (b->size & PREV_STATE); 939 b->size = new_size | (b->size & PREV_STATE);
849 } 940 }
850 TLSF_ADD_SIZE(tlsf, b); 941 TLSF_ADD_SIZE(tlsf, b);
851 return (void *) b->ptr.buffer; 942 return (void *) b->ptr.buffer;
852 } 943 }
853 if ((next_b->size & FREE_BLOCK)) { 944 if ((next_b->size & FREE_BLOCK)) {
854 if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) { 945 if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) {
946 /* allocate out of next block */
855 TLSF_REMOVE_SIZE(tlsf, b); 947 TLSF_REMOVE_SIZE(tlsf, b);
856 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl); 948 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
857 EXTRACT_BLOCK(next_b, tlsf, fl, sl); 949 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
858 b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD; 950 b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
859 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE); 951 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
860 next_b->prev_hdr = b;
861 next_b->size &= ~PREV_FREE; 952 next_b->size &= ~PREV_FREE;
953 next_b->prev_hdr = encode_prev_block( b, next_b->size );
862 tmp_size = (b->size & BLOCK_SIZE) - new_size; 954 tmp_size = (b->size & BLOCK_SIZE) - new_size;
863 if (tmp_size >= sizeof(bhdr_t)) { 955 if (tmp_size >= sizeof(bhdr_t)) {
864 tmp_size -= BHDR_OVERHEAD; 956 tmp_size -= BHDR_OVERHEAD;
865 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size); 957 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
866 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED; 958 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
867 next_b->prev_hdr = tmp_b;
868 next_b->size |= PREV_FREE; 959 next_b->size |= PREV_FREE;
960 next_b->prev_hdr = encode_prev_block(tmp_b, next_b->size);
869 MAPPING_INSERT(tmp_size, &fl, &sl); 961 MAPPING_INSERT(tmp_size, &fl, &sl);
870 INSERT_BLOCK(tmp_b, tlsf, fl, sl); 962 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
871 b->size = new_size | (b->size & PREV_STATE); 963 b->size = new_size | (b->size & PREV_STATE);
872 } 964 }
873 TLSF_ADD_SIZE(tlsf, b); 965 TLSF_ADD_SIZE(tlsf, b);
874 return (void *) b->ptr.buffer; 966 return (void *) b->ptr.buffer;
875 } 967 }
876 } 968 }
877 969
878 if (!(ptr_aux = malloc_ex(new_size, mem_pool))) 970 if (!(ptr_aux = malloc_ex(new_size, mem_pool))){
879 return NULL; 971 return NULL;
972 }
880 973
881 cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE); 974 cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE);
882 975
@@ -971,7 +1064,7 @@ void print_block(bhdr_t * b)
971 else 1064 else
972 PRINT_MSG("used, "); 1065 PRINT_MSG("used, ");
973 if ((b->size & PREV_STATE) == PREV_FREE) 1066 if ((b->size & PREV_STATE) == PREV_FREE)
974 PRINT_MSG("prev. free [%p])\n", b->prev_hdr); 1067 PRINT_MSG("prev. free [%p])\n", b->prev_hdr & BLOCK_SIZE);
975 else 1068 else
976 PRINT_MSG("prev used)\n"); 1069 PRINT_MSG("prev used)\n");
977} 1070}