00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef __APPLE__
00058 #define _DARWIN_C_SOURCE
00059 #endif
00060
00061 #include "../fosi.h"
00062 #include <string.h>
00063
00064 #define TLSF_USE_LOCKS (1)
00065
00066 #ifndef TLSF_STATISTIC
00067 #define TLSF_STATISTIC (0)
00068 #endif
00069
00070 #ifndef USE_MMAP
00071 #define USE_MMAP (0)
00072 #endif
00073
00074 #ifndef USE_SBRK
00075 #define USE_SBRK (0)
00076 #endif
00077
00078
00079 #if TLSF_USE_LOCKS
00080 #include "target.h"
00081 #else
00082 #define TLSF_CREATE_LOCK(_unused_) do{}while(0)
00083 #define TLSF_DESTROY_LOCK(_unused_) do{}while(0)
00084 #define TLSF_ACQUIRE_LOCK(_unused_) do{}while(0)
00085 #define TLSF_RELEASE_LOCK(_unused_) do{}while(0)
00086 #endif
00087
00088 #if TLSF_STATISTIC
00089 #define TLSF_ADD_SIZE(tlsf, b) do { \
00090 tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
00091 if (tlsf->used_size > tlsf->max_size) \
00092 tlsf->max_size = tlsf->used_size; \
00093 } while(0)
00094
00095 #define TLSF_REMOVE_SIZE(tlsf, b) do { \
00096 tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD; \
00097 } while(0)
00098 #else
00099 #define TLSF_ADD_SIZE(tlsf, b) do{}while(0)
00100 #define TLSF_REMOVE_SIZE(tlsf, b) do{}while(0)
00101 #endif
00102
00103 #if USE_MMAP || USE_SBRK
00104 #include <unistd.h>
00105 #endif
00106
00107 #if USE_MMAP
00108 #include <sys/mman.h>
00109
00110 #ifdef __APPLE__
00111 #define TLSF_MAP MAP_PRIVATE | MAP_ANON
00112 #else
00113 #define TLSF_MAP MAP_PRIVATE | MAP_ANONYMOUS
00114 #endif
00115 #endif
00116
00117 #define ORO_MEMORY_POOL
00118 #include "tlsf.h"
00119
00120 #if !defined(__GNUC__)
00121 #ifndef __inline__
00122 #define __inline__
00123 #endif
00124 #endif
00125
00126
00127 #ifndef _DEBUG_TLSF_
00128 #define _DEBUG_TLSF_ (0)
00129 #endif
00130
00131
00132
00133
00134
00135
00136
00137 #define BLOCK_ALIGN (sizeof(void *) * 2)
00138
00139 #define MAX_FLI (30)
00140 #define MAX_LOG2_SLI (5)
00141 #define MAX_SLI (1 << MAX_LOG2_SLI)
00142
00143 #define FLI_OFFSET (6)
00144
00145 #define SMALL_BLOCK (128)
00146 #define REAL_FLI (MAX_FLI - FLI_OFFSET)
00147 #define MIN_BLOCK_SIZE (sizeof (free_ptr_t))
00148 #define BHDR_OVERHEAD (sizeof (bhdr_t) - MIN_BLOCK_SIZE)
00149 #define TLSF_SIGNATURE (0x2A59FA59)
00150
00151 #define PTR_MASK (sizeof(void *) - 1)
00152 #define BLOCK_SIZE (0xFFFFFFFF - PTR_MASK)
00153
00154 #define GET_NEXT_BLOCK(_addr, _r) ((bhdr_t *) ((char *) (_addr) + (_r)))
00155 #define MEM_ALIGN ((BLOCK_ALIGN) - 1)
00156 #define ROUNDUP_SIZE(_r) (((_r) + MEM_ALIGN) & ~MEM_ALIGN)
00157 #define ROUNDDOWN_SIZE(_r) ((_r) & ~MEM_ALIGN)
00158 #define ROUNDUP(_x, _v) ((((~(_x)) + 1) & ((_v)-1)) + (_x))
00159
00160 #define BLOCK_STATE (0x1)
00161 #define PREV_STATE (0x2)
00162
00163
00164 #define FREE_BLOCK (0x1)
00165 #define USED_BLOCK (0x0)
00166
00167
00168 #define PREV_FREE (0x2)
00169 #define PREV_USED (0x0)
00170
00171
00172 #define DEFAULT_AREA_SIZE (1024*10)
00173
00174 #if USE_MMAP
00175 #define TLSF_PAGE_SIZE (getpagesize())
00176 #endif
00177
00178 #define PRINT_MSG(fmt, args...) printf(fmt, ## args)
00179 #define ERROR_MSG(fmt, args...) printf(fmt, ## args)
00180
00181 typedef unsigned int u32_t;
00182 typedef unsigned char u8_t;
00183
00184 typedef struct free_ptr_struct {
00185 struct bhdr_struct *prev;
00186 struct bhdr_struct *next;
00187 } free_ptr_t;
00188
00189 typedef struct bhdr_struct {
00190
00191 struct bhdr_struct *prev_hdr;
00192
00193 size_t size;
00194
00195 union {
00196 struct free_ptr_struct free_ptr;
00197 u8_t buffer[1];
00198 } ptr;
00199 } bhdr_t;
00200
00201
00202
00203
00204 typedef struct area_info_struct {
00205 bhdr_t *end;
00206 struct area_info_struct *next;
00207 } area_info_t;
00208
00209 typedef struct TLSF_struct {
00210
00211 u32_t tlsf_signature;
00212
00213 #if TLSF_USE_LOCKS
00214 TLSF_MLOCK_T lock;
00215 #endif
00216
00217 #if TLSF_STATISTIC
00218
00219
00220 size_t used_size;
00221 size_t max_size;
00222 #endif
00223
00224
00225 area_info_t *area_head;
00226
00227
00228
00229 u32_t fl_bitmap;
00230
00231
00232 u32_t sl_bitmap[REAL_FLI];
00233
00234 bhdr_t *matrix[REAL_FLI][MAX_SLI];
00235 } tlsf_t;
00236
00237
00238
00239
00240
00241 static __inline__ void set_bit(int nr, u32_t * addr);
00242 static __inline__ void clear_bit(int nr, u32_t * addr);
00243 static __inline__ int ls_bit(int x);
00244 static __inline__ int ms_bit(int x);
00245 static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl);
00246 static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl);
00247 static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl);
00248 static __inline__ bhdr_t *process_area(void *area, size_t size);
00249 #if USE_SBRK || USE_MMAP
00250 static __inline__ void *get_new_area(size_t * size);
00251 #endif
00252
00253 static const int table[] = {
00254 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
00255 4, 4,
00256 4, 4, 4, 4, 4, 4, 4,
00257 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
00258 5,
00259 5, 5, 5, 5, 5, 5, 5,
00260 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00261 6,
00262 6, 6, 6, 6, 6, 6, 6,
00263 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00264 6,
00265 6, 6, 6, 6, 6, 6, 6,
00266 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00267 7,
00268 7, 7, 7, 7, 7, 7, 7,
00269 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00270 7,
00271 7, 7, 7, 7, 7, 7, 7,
00272 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00273 7,
00274 7, 7, 7, 7, 7, 7, 7,
00275 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
00276 7,
00277 7, 7, 7, 7, 7, 7, 7
00278 };
00279
00280 static __inline__ int ls_bit(int i)
00281 {
00282 unsigned int a;
00283 unsigned int x = i & -i;
00284
00285 a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
00286 return table[x >> a] + a;
00287 }
00288
00289 static __inline__ int ms_bit(int i)
00290 {
00291 unsigned int a;
00292 unsigned int x = (unsigned int) i;
00293
00294 a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
00295 return table[x >> a] + a;
00296 }
00297
00298 static __inline__ void set_bit(int nr, u32_t * addr)
00299 {
00300 addr[nr >> 5] |= 1 << (nr & 0x1f);
00301 }
00302
00303 static __inline__ void clear_bit(int nr, u32_t * addr)
00304 {
00305 addr[nr >> 5] &= ~(1 << (nr & 0x1f));
00306 }
00307
00308 static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl)
00309 {
00310 int _t;
00311
00312 if (*_r < SMALL_BLOCK) {
00313 *_fl = 0;
00314 *_sl = *_r / (SMALL_BLOCK / MAX_SLI);
00315 } else {
00316 _t = (1 << (ms_bit(*_r) - MAX_LOG2_SLI)) - 1;
00317 *_r = *_r + _t;
00318 *_fl = ms_bit(*_r);
00319 *_sl = (*_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
00320 *_fl -= FLI_OFFSET;
00321
00322
00323
00324 *_r &= ~_t;
00325 }
00326 }
00327
00328 static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl)
00329 {
00330 if (_r < SMALL_BLOCK) {
00331 *_fl = 0;
00332 *_sl = _r / (SMALL_BLOCK / MAX_SLI);
00333 } else {
00334 *_fl = ms_bit(_r);
00335 *_sl = (_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
00336 *_fl -= FLI_OFFSET;
00337 }
00338 }
00339
00340
00341 static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl)
00342 {
00343 u32_t _tmp = _tlsf->sl_bitmap[*_fl] & (~0 << *_sl);
00344 bhdr_t *_b = NULL;
00345
00346 if (_tmp) {
00347 *_sl = ls_bit(_tmp);
00348 _b = _tlsf->matrix[*_fl][*_sl];
00349 } else {
00350 *_fl = ls_bit(_tlsf->fl_bitmap & (~0 << (*_fl + 1)));
00351 if (*_fl > 0) {
00352 *_sl = ls_bit(_tlsf->sl_bitmap[*_fl]);
00353 _b = _tlsf->matrix[*_fl][*_sl];
00354 }
00355 }
00356 return _b;
00357 }
00358
00359
00360 #define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) do { \
00361 _tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next; \
00362 if (_tlsf -> matrix[_fl][_sl]) \
00363 _tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL; \
00364 else { \
00365 clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \
00366 if (!_tlsf -> sl_bitmap [_fl]) \
00367 clear_bit (_fl, &_tlsf -> fl_bitmap); \
00368 } \
00369 _b -> ptr.free_ptr.prev = NULL; \
00370 _b -> ptr.free_ptr.next = NULL; \
00371 }while(0)
00372
00373
00374 #define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) do { \
00375 if (_b -> ptr.free_ptr.next) \
00376 _b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \
00377 if (_b -> ptr.free_ptr.prev) \
00378 _b -> ptr.free_ptr.prev -> ptr.free_ptr.next = _b -> ptr.free_ptr.next; \
00379 if (_tlsf -> matrix [_fl][_sl] == _b) { \
00380 _tlsf -> matrix [_fl][_sl] = _b -> ptr.free_ptr.next; \
00381 if (!_tlsf -> matrix [_fl][_sl]) { \
00382 clear_bit (_sl, &_tlsf -> sl_bitmap[_fl]); \
00383 if (!_tlsf -> sl_bitmap [_fl]) \
00384 clear_bit (_fl, &_tlsf -> fl_bitmap); \
00385 } \
00386 } \
00387 _b -> ptr.free_ptr.prev = NULL; \
00388 _b -> ptr.free_ptr.next = NULL; \
00389 } while(0)
00390
00391 #define INSERT_BLOCK(_b, _tlsf, _fl, _sl) do { \
00392 _b -> ptr.free_ptr.prev = NULL; \
00393 _b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \
00394 if (_tlsf -> matrix [_fl][_sl]) \
00395 _tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b; \
00396 _tlsf -> matrix [_fl][_sl] = _b; \
00397 set_bit (_sl, &_tlsf -> sl_bitmap [_fl]); \
00398 set_bit (_fl, &_tlsf -> fl_bitmap); \
00399 } while(0)
00400
00401 #if USE_SBRK || USE_MMAP
00402 static __inline__ void *get_new_area(size_t * size)
00403 {
00404 void *area;
00405
00406 #if USE_SBRK
00407 area = (void *)sbrk(0);
00408 if (((void *)sbrk(*size)) != ((void *) -1))
00409 return area;
00410 #endif
00411
00412 #if USE_MMAP
00413 *size = ROUNDUP(*size, TLSF_PAGE_SIZE);
00414 if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, TLSF_MAP, -1, 0)) != MAP_FAILED)
00415 return area;
00416 #endif
00417 return ((void *) ~0);
00418 }
00419 #endif
00420
00421 static __inline__ bhdr_t *process_area(void *area, size_t size)
00422 {
00423 bhdr_t *b, *lb, *ib;
00424 area_info_t *ai;
00425
00426 ib = (bhdr_t *) area;
00427 ib->size =
00428 (sizeof(area_info_t) <
00429 MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED;
00430 b = (bhdr_t *) GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
00431 b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED;
00432 b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0;
00433 lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00434 lb->prev_hdr = b;
00435 lb->size = 0 | USED_BLOCK | PREV_FREE;
00436 ai = (area_info_t *) ib->ptr.buffer;
00437 ai->next = 0;
00438 ai->end = lb;
00439 return ib;
00440 }
00441
00442
00443
00444
00445
00446 static char *mp = NULL;
00447 static int init_check = 0;
00448
00449
00450 size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
00451 {
00452
00453 tlsf_t *tlsf;
00454 bhdr_t *b, *ib;
00455
00456 if (!mem_pool || !mem_pool_size || mem_pool_size < sizeof(tlsf_t) + BHDR_OVERHEAD * 8) {
00457 ERROR_MSG("init_memory_pool (): memory_pool invalid\n");
00458 return -1;
00459 }
00460
00461 if (((unsigned long) mem_pool & PTR_MASK)) {
00462 ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n");
00463 return -1;
00464 }
00465 tlsf = (tlsf_t *) mem_pool;
00466
00467 if (init_check) {
00468 mp = mem_pool;
00469 b = GET_NEXT_BLOCK(mp, ROUNDUP_SIZE(sizeof(tlsf_t)));
00470 return b->size & BLOCK_SIZE;
00471 }
00472
00473 mp = mem_pool;
00474
00475
00476 memset(mem_pool, 0, sizeof(tlsf_t));
00477
00478 tlsf->tlsf_signature = TLSF_SIGNATURE;
00479 init_check = 1;
00480
00481 TLSF_CREATE_LOCK(&tlsf->lock);
00482
00483 ib = process_area(GET_NEXT_BLOCK
00484 (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));
00485 b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
00486 free_ex(b->ptr.buffer, tlsf);
00487 tlsf->area_head = (area_info_t *) ib->ptr.buffer;
00488
00489 #if TLSF_STATISTIC
00490 tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE);
00491 tlsf->max_size = tlsf->used_size;
00492 #endif
00493
00494 return (b->size & BLOCK_SIZE);
00495 }
00496
00497
00498 size_t add_new_area(void *area, size_t area_size, void *mem_pool)
00499 {
00500
00501 tlsf_t *tlsf = (tlsf_t *) mem_pool;
00502 area_info_t *ptr, *ptr_prev, *ai;
00503 bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b;
00504
00505 memset(area, 0, area_size);
00506 ptr = tlsf->area_head;
00507 ptr_prev = 0;
00508
00509 ib0 = process_area(area, area_size);
00510 b0 = GET_NEXT_BLOCK(ib0->ptr.buffer, ib0->size & BLOCK_SIZE);
00511 lb0 = GET_NEXT_BLOCK(b0->ptr.buffer, b0->size & BLOCK_SIZE);
00512
00513
00514
00515
00516 while (ptr) {
00517 ib1 = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
00518 b1 = GET_NEXT_BLOCK(ib1->ptr.buffer, ib1->size & BLOCK_SIZE);
00519 lb1 = ptr->end;
00520
00521
00522 if ((unsigned long) ib1 == (unsigned long) lb0 + BHDR_OVERHEAD) {
00523 if (tlsf->area_head == ptr) {
00524 tlsf->area_head = ptr->next;
00525 ptr = ptr->next;
00526 } else {
00527 ptr_prev->next = ptr->next;
00528 ptr = ptr->next;
00529 }
00530
00531 b0->size =
00532 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
00533 (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED;
00534
00535 b1->prev_hdr = b0;
00536 lb0 = lb1;
00537
00538 continue;
00539 }
00540
00541
00542
00543 if ((unsigned long) lb1->ptr.buffer == (unsigned long) ib0) {
00544 if (tlsf->area_head == ptr) {
00545 tlsf->area_head = ptr->next;
00546 ptr = ptr->next;
00547 } else {
00548 ptr_prev->next = ptr->next;
00549 ptr = ptr->next;
00550 }
00551
00552 lb1->size =
00553 ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
00554 (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE);
00555 next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE);
00556 next_b->prev_hdr = lb1;
00557 b0 = lb1;
00558 ib0 = ib1;
00559
00560 continue;
00561 }
00562 ptr_prev = ptr;
00563 ptr = ptr->next;
00564 }
00565
00566
00567 ai = (area_info_t *) ib0->ptr.buffer;
00568 ai->next = tlsf->area_head;
00569 ai->end = lb0;
00570 tlsf->area_head = ai;
00571 free_ex(b0->ptr.buffer, mem_pool);
00572 return (b0->size & BLOCK_SIZE);
00573 }
00574
00575
00576
00577 size_t get_used_size(void *mem_pool)
00578 {
00579
00580 #if TLSF_STATISTIC
00581 return ((tlsf_t *) mem_pool)->used_size;
00582 #else
00583 return 0;
00584 #endif
00585 }
00586
00587
00588 size_t get_max_size(void *mem_pool)
00589 {
00590
00591 #if TLSF_STATISTIC
00592 return ((tlsf_t *) mem_pool)->max_size;
00593 #else
00594 return 0;
00595 #endif
00596 }
00597
00598
00599 void destroy_memory_pool(void *mem_pool)
00600 {
00601
00602 tlsf_t *tlsf = (tlsf_t *) mem_pool;
00603
00604 tlsf->tlsf_signature = 0;
00605
00606 TLSF_DESTROY_LOCK(&tlsf->lock);
00607
00608 }
00609
00610
00611
00612 void *tlsf_malloc(size_t size)
00613 {
00614
00615 void *ret;
00616
00617 #if USE_MMAP || USE_SBRK
00618 if (!mp) {
00619 size_t area_size;
00620 void *area;
00621
00622 area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8;
00623 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
00624 area = get_new_area(&area_size);
00625 if (area == ((void *) ~0))
00626 return NULL;
00627 init_memory_pool(area_size, area);
00628 }
00629 #endif
00630
00631 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
00632
00633 ret = malloc_ex(size, mp);
00634
00635 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
00636
00637 return ret;
00638 }
00639
00640
00641 void tlsf_free(void *ptr)
00642 {
00643
00644
00645 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
00646
00647 free_ex(ptr, mp);
00648
00649 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
00650
00651 }
00652
00653
00654 void *tlsf_realloc(void *ptr, size_t size)
00655 {
00656
00657 void *ret;
00658
00659 #if USE_MMAP || USE_SBRK
00660 if (!mp) {
00661 return tlsf_malloc(size);
00662 }
00663 #endif
00664
00665 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
00666
00667 ret = realloc_ex(ptr, size, mp);
00668
00669 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
00670
00671 return ret;
00672 }
00673
00674
00675 void *tlsf_calloc(size_t nelem, size_t elem_size)
00676 {
00677
00678 void *ret;
00679
00680 TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
00681
00682 ret = calloc_ex(nelem, elem_size, mp);
00683
00684 TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
00685
00686 return ret;
00687 }
00688
00689
00690 void *malloc_ex(size_t size, void *mem_pool)
00691 {
00692
00693 tlsf_t *tlsf = (tlsf_t *) mem_pool;
00694 bhdr_t *b, *b2, *next_b;
00695 int fl, sl;
00696 size_t tmp_size;
00697
00698 size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size);
00699
00700
00701 MAPPING_SEARCH(&size, &fl, &sl);
00702
00703
00704
00705 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
00706 #if USE_MMAP || USE_SBRK
00707 if (!b) {
00708 size_t area_size;
00709 void *area;
00710
00711 area_size = size + BHDR_OVERHEAD * 8;
00712 area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
00713 area = get_new_area(&area_size);
00714 if (area == ((void *) ~0))
00715 return NULL;
00716 add_new_area(area, area_size, mem_pool);
00717
00718 MAPPING_SEARCH(&size, &fl, &sl);
00719
00720 b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
00721 }
00722 #endif
00723 if (!b)
00724 return NULL;
00725
00726 EXTRACT_BLOCK_HDR(b, tlsf, fl, sl);
00727
00728
00729 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00730
00731 tmp_size = (b->size & BLOCK_SIZE) - size;
00732 if (tmp_size >= sizeof(bhdr_t)) {
00733 tmp_size -= BHDR_OVERHEAD;
00734 b2 = GET_NEXT_BLOCK(b->ptr.buffer, size);
00735 b2->size = tmp_size | FREE_BLOCK | PREV_USED;
00736 next_b->prev_hdr = b2;
00737 MAPPING_INSERT(tmp_size, &fl, &sl);
00738 INSERT_BLOCK(b2, tlsf, fl, sl);
00739
00740 b->size = size | (b->size & PREV_STATE);
00741 } else {
00742 next_b->size &= (~PREV_FREE);
00743 b->size &= (~FREE_BLOCK);
00744 }
00745
00746 TLSF_ADD_SIZE(tlsf, b);
00747
00748 return (void *) b->ptr.buffer;
00749 }
00750
00751
00752 void free_ex(void *ptr, void *mem_pool)
00753 {
00754
00755 tlsf_t *tlsf = (tlsf_t *) mem_pool;
00756 bhdr_t *b, *tmp_b;
00757 int fl = 0, sl = 0;
00758
00759 if (!ptr) {
00760 return;
00761 }
00762 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
00763 b->size |= FREE_BLOCK;
00764
00765 TLSF_REMOVE_SIZE(tlsf, b);
00766
00767 b->ptr.free_ptr.prev = NULL;
00768 b->ptr.free_ptr.next = NULL;
00769 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00770 if (tmp_b->size & FREE_BLOCK) {
00771 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
00772 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
00773 b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
00774 }
00775 if (b->size & PREV_FREE) {
00776 tmp_b = b->prev_hdr;
00777 MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
00778 EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
00779 tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
00780 b = tmp_b;
00781 }
00782 MAPPING_INSERT(b->size & BLOCK_SIZE, &fl, &sl);
00783 INSERT_BLOCK(b, tlsf, fl, sl);
00784
00785 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00786 tmp_b->size |= PREV_FREE;
00787 tmp_b->prev_hdr = b;
00788 }
00789
00790
00791 void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
00792 {
00793
00794 tlsf_t *tlsf = (tlsf_t *) mem_pool;
00795 void *ptr_aux;
00796 unsigned int cpsize;
00797 bhdr_t *b, *tmp_b, *next_b;
00798 int fl, sl;
00799 size_t tmp_size;
00800
00801 if (!ptr) {
00802 if (new_size)
00803 return (void *) malloc_ex(new_size, mem_pool);
00804 if (!new_size)
00805 return NULL;
00806 } else if (!new_size) {
00807 free_ex(ptr, mem_pool);
00808 return NULL;
00809 }
00810
00811 b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
00812 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00813 new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size);
00814 tmp_size = (b->size & BLOCK_SIZE);
00815 if (new_size <= tmp_size) {
00816 TLSF_REMOVE_SIZE(tlsf, b);
00817 if (next_b->size & FREE_BLOCK) {
00818 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
00819 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
00820 tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
00821 next_b = GET_NEXT_BLOCK(next_b->ptr.buffer, next_b->size & BLOCK_SIZE);
00822
00823
00824 }
00825 tmp_size -= new_size;
00826 if (tmp_size >= sizeof(bhdr_t)) {
00827 tmp_size -= BHDR_OVERHEAD;
00828 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
00829 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
00830 next_b->prev_hdr = tmp_b;
00831 next_b->size |= PREV_FREE;
00832 MAPPING_INSERT(tmp_size, &fl, &sl);
00833 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
00834 b->size = new_size | (b->size & PREV_STATE);
00835 }
00836 TLSF_ADD_SIZE(tlsf, b);
00837 return (void *) b->ptr.buffer;
00838 }
00839 if ((next_b->size & FREE_BLOCK)) {
00840 if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) {
00841 TLSF_REMOVE_SIZE(tlsf, b);
00842 MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
00843 EXTRACT_BLOCK(next_b, tlsf, fl, sl);
00844 b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
00845 next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
00846 next_b->prev_hdr = b;
00847 next_b->size &= ~PREV_FREE;
00848 tmp_size = (b->size & BLOCK_SIZE) - new_size;
00849 if (tmp_size >= sizeof(bhdr_t)) {
00850 tmp_size -= BHDR_OVERHEAD;
00851 tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
00852 tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
00853 next_b->prev_hdr = tmp_b;
00854 next_b->size |= PREV_FREE;
00855 MAPPING_INSERT(tmp_size, &fl, &sl);
00856 INSERT_BLOCK(tmp_b, tlsf, fl, sl);
00857 b->size = new_size | (b->size & PREV_STATE);
00858 }
00859 TLSF_ADD_SIZE(tlsf, b);
00860 return (void *) b->ptr.buffer;
00861 }
00862 }
00863
00864 ptr_aux = malloc_ex(new_size, mem_pool);
00865
00866 cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE);
00867
00868 memcpy(ptr_aux, ptr, cpsize);
00869
00870 free_ex(ptr, mem_pool);
00871 return ptr_aux;
00872 }
00873
00874
00875
00876 void *calloc_ex(size_t nelem, size_t elem_size, void *mem_pool)
00877 {
00878
00879 void *ptr;
00880
00881 if (nelem <= 0 || elem_size <= 0)
00882 return NULL;
00883
00884 if (!(ptr = malloc_ex(nelem * elem_size, mem_pool)))
00885 return NULL;
00886 memset(ptr, 0, nelem * elem_size);
00887
00888 return ptr;
00889 }
00890
00891
00892
00893 #if _DEBUG_TLSF_
00894
00895
00896
00897
00898
00899
00900
00901 extern void dump_memory_region(unsigned char *mem_ptr, unsigned int size);
00902 extern void print_block(bhdr_t * b);
00903 extern void print_tlsf(tlsf_t * tlsf);
00904 void print_all_blocks(tlsf_t * tlsf);
00905
00906 void dump_memory_region(unsigned char *mem_ptr, unsigned int size)
00907 {
00908
00909 unsigned long begin = (unsigned long) mem_ptr;
00910 unsigned long end = (unsigned long) mem_ptr + size;
00911 int column = 0;
00912
00913 begin >>= 2;
00914 begin <<= 2;
00915
00916 end >>= 2;
00917 end++;
00918 end <<= 2;
00919
00920 PRINT_MSG("\nMemory region dumped: 0x%lx - 0x%lx\n\n", begin, end);
00921
00922 column = 0;
00923 PRINT_MSG("0x%lx ", begin);
00924
00925 while (begin < end) {
00926 if (((unsigned char *) begin)[0] == 0)
00927 PRINT_MSG("00");
00928 else
00929 PRINT_MSG("%02x", ((unsigned char *) begin)[0]);
00930 if (((unsigned char *) begin)[1] == 0)
00931 PRINT_MSG("00 ");
00932 else
00933 PRINT_MSG("%02x ", ((unsigned char *) begin)[1]);
00934 begin += 2;
00935 column++;
00936 if (column == 8) {
00937 PRINT_MSG("\n0x%lx ", begin);
00938 column = 0;
00939 }
00940
00941 }
00942 PRINT_MSG("\n\n");
00943 }
00944
00945 void print_block(bhdr_t * b)
00946 {
00947 if (!b)
00948 return;
00949 PRINT_MSG(">> [%p] (", b);
00950 if ((b->size & BLOCK_SIZE))
00951 PRINT_MSG("%lu bytes, ", (unsigned long) (b->size & BLOCK_SIZE));
00952 else
00953 PRINT_MSG("sentinel, ");
00954 if ((b->size & BLOCK_STATE) == FREE_BLOCK)
00955 PRINT_MSG("free [%p, %p], ", b->ptr.free_ptr.prev, b->ptr.free_ptr.next);
00956 else
00957 PRINT_MSG("used, ");
00958 if ((b->size & PREV_STATE) == PREV_FREE)
00959 PRINT_MSG("prev. free [%p])\n", b->prev_hdr);
00960 else
00961 PRINT_MSG("prev used)\n");
00962 }
00963
00964 void print_tlsf(tlsf_t * tlsf)
00965 {
00966 bhdr_t *next;
00967 int i, j;
00968
00969 PRINT_MSG("\nTLSF at %p\n", tlsf);
00970
00971 PRINT_MSG("FL bitmap: 0x%x\n\n", (unsigned) tlsf->fl_bitmap);
00972
00973 for (i = 0; i < REAL_FLI; i++) {
00974 if (tlsf->sl_bitmap[i])
00975 PRINT_MSG("SL bitmap 0x%x\n", (unsigned) tlsf->sl_bitmap[i]);
00976 for (j = 0; j < MAX_SLI; j++) {
00977 next = tlsf->matrix[i][j];
00978 if (next)
00979 PRINT_MSG("-> [%d][%d]\n", i, j);
00980 while (next) {
00981 print_block(next);
00982 next = next->ptr.free_ptr.next;
00983 }
00984 }
00985 }
00986 }
00987
00988 void print_all_blocks(tlsf_t * tlsf)
00989 {
00990 area_info_t *ai;
00991 bhdr_t *next;
00992 PRINT_MSG("\nTLSF at %p\nALL BLOCKS\n\n", tlsf);
00993 ai = tlsf->area_head;
00994 while (ai) {
00995 next = (bhdr_t *) ((char *) ai - BHDR_OVERHEAD);
00996 while (next) {
00997 print_block(next);
00998 if ((next->size & BLOCK_SIZE))
00999 next = GET_NEXT_BLOCK(next->ptr.buffer, next->size & BLOCK_SIZE);
01000 else
01001 next = NULL;
01002 }
01003 ai = ai->next;
01004 }
01005 }
01006
01007 #endif