Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

rtl_malloc.c

Go to the documentation of this file.
00001 /*
00002  * Two Levels Segregate Fit memory allocator (TLSF)
00003  * Version 1.1
00004  *
00005  * Written by Miguel Masmano Tello <mmasmano@disca.upv.es>
00006  * Copyright (C) Dec, 2002 OCERA Consortium
00007  * Release under the terms of the GNU General Public License Version 2
00008  *
00009  */
00010 
00011 #include "rtl_malloc.h"
00012 #include "arch/bits.h"
00013 
00014 // linux/types.h includes definitions
00015 // for the standard types
00016 // #include <linux/types.h>
00017 
00018 #if !defined (__RTL__) && defined (__KERNEL__)
00019 #error "This modules can only be used by RTLinux or by user space"
00020 #endif
00021 
00022 #if defined (__RTL__)
00023 
00024 #include <linux/config.h>
00025 
00026 #define INIT_THREAD_MUTEX()
00027 #define THREAD_LOCK() __asm__ __volatile__ ("cli");
00028 #define THREAD_UNLOCK() __asm__ __volatile__ ("sti");
00029 
00030 MODULE_AUTHOR("Miguel Masmano Tello <mmasmano@disca.upv.es>");
00031 MODULE_DESCRIPTION("Three Levels Segregate Fit memory allocator (TLSF) V1.0");
00032 
00033 MODULE_LICENSE("GPL");
00034 
00035 static int max_size = 1024; // 1 MByte
00036 
00037 MODULE_PARM(max_size, "i");
00038 MODULE_PARM_DESC(max_size, "Memory pool size in Kb (default=1024)");
00039 
00040 static unsigned char *ptr_mem;
00041 
00042 /* This TLSF version only can be used with BIGPHYSAREA patch */
00043 #if defined(CONFIG_BIGPHYSAREA) || defined(CONFIG_BIGPHYS_AREA)
00044 #include <linux/bigphysarea.h>
00045 #else
00046 #error BIGPHYSAREA LINUX KERNEL PATCH MUST BE INSTALLED
00047 #endif
00048 
00049 int init_module(void){
00050   // First of all we reserve the memory that will be used later
00051   ptr_mem = (unsigned char *) bigphysarea_alloc(max_size * 1024);
00052   if (ptr_mem == NULL) { 
00053     rtl_printf ("rtl_malloc PANIC: Error reserving memory!!");
00054     return -1; 
00055   }
00056   if (init_memory_pool (max_size, 5, ptr_mem) < 0) return -1;
00057   associate_buffer (ptr_mem);
00058   
00059   return 0;
00060 }
00061 
00062 void cleanup_module(void){
00063   destroy_memory_pool(ptr_mem);
00064   bigphysarea_free((caddr_t) ptr_mem, 0);
00065 }
00066 
00067 #else // #if defined (__RTL__)
00068 
00069 #define INIT_THREAD_MUTEX()
00070 #define THREAD_LOCK()
00071 #define THREAD_UNLOCK()
00072 
00073 #endif // #if defined (__RTL__)
00074 
00075 /*
00076  * The following  TAD will be a  double level indexed  array, the most
00077  * important thing is that the time  is bounded, the reason of this is
00078  * because TLSF has been designed to be used by real time programs.
00079  *
00080  *     First level       Second level
00081  *     it is indexed     it is indexed by 2**n+(2**n/m*index_number)
00082  *     by power of 2
00083  *                            0             1     m-1        m
00084  *                            ----> NULL   --> NULL          ----> NUL
00085  *                            |            |                 |
00086  *       -------         ---------------------...---------------------
00087  *  2**n |  n  |  -----> |2**n+(2**n/m*0)|...|   |...|2**n+(2**n/m*m)|
00088  *       |-----|         ---------------------...---------------------
00089  * 2**n-1| n-1 |  -----> ....                      |
00090  *       |-----|                                   --->NULL
00091  *        .....
00092  */
00093 
00094 /* 
00095  * Some defaults values;
00096  * please, don't touch these macros
00097  */
00098 
00099 #define TLSF_WORD_SIZE 4 //(sizeof(__u32))
00100 #define LOG2_TLSF_WORD_SIZE 2 //(TLSF_fls(TLSF_WORD_SIZE)) // TLSF_WORD size
00101 
00102 
00103 
00104 #define MIN_LOG2_SIZE 2 // 16 bytes
00105 #define MIN_SIZE 4 //(1 << MIN_LOG2_SIZE)
00106 
00107 #define TLSF_WORDS2BYTES(x) ((x) << LOG2_TLSF_WORD_SIZE)
00108 #define BYTES2TLSF_WORDS(x) ((x) >> LOG2_TLSF_WORD_SIZE)
00109 
00110 /* 
00111  * The following structure defines the pointers used 
00112  * by the header to know the position of the free blocks 
00113  */
00114 
00115 typedef struct free_ptr_struct {
00116   struct block_header_struct *prev;
00117   struct block_header_struct *next;
00118 
00119   /* 
00120    * first_index and second_index are used to store
00121    * mapping_function results, that's how we get some extra
00122    * nanoseconds 
00123    */
00124   __u8 first_index;
00125   __u8 second_index;
00126 } free_ptr_t;
00127 
00128 /*
00129  * USED_BLOCK must be used like mask with the magic number
00130  * i.e. 
00131  * if ((magic_number & USED_BLOCK) = USED_BLOCK) then
00132  *   return USED;
00133  * else
00134  *   return FREE
00135  * end if;
00136  */
00137 
00138 #define USED_BLOCK 0x80000000
00139 #define FREE_BLOCK ~USED_BLOCK //0x7FFFFFFF
00140 
00141 #define LAST_BLOCK 0x40000000
00142 #define NOT_LAST_BLOCK ~LAST_BLOCK //0xBFFFFFFF
00143 
00144 #define IS_USED_BLOCK(x) ((x -> size & USED_BLOCK) == USED_BLOCK)
00145 #define IS_LAST_BLOCK(x) ((x -> size & LAST_BLOCK) == LAST_BLOCK)
00146 #define GET_BLOCK_SIZE(x) (x -> size & FREE_BLOCK & NOT_LAST_BLOCK)
00147 #define SET_USED_BLOCK(x) (x -> size |= USED_BLOCK)
00148 #define SET_FREE_BLOCK(x) (x -> size &= FREE_BLOCK)
00149 #define SET_LAST_BLOCK(x) (x -> size |= LAST_BLOCK)
00150 #define SET_NOT_LAST_BLOCK(x) (x -> size &= NOT_LAST_BLOCK)
00151 
00152 #define MAGIC_NUMBER 0x2A59FA59
00153 
00154 typedef struct block_header_struct {
00155   /* 
00156    * size codifies the block size in TLSF_BYTES and it also codifies if 
00157    * the block is used or free 
00158    */
00159   
00160   __u32 size;
00161   
00162   /* The following pointer points to the previous physical block */
00163   struct block_header_struct *prev_phys_block;
00164 
00165   union {
00166     struct free_ptr_struct free_ptr;
00167     __u8 buffer[sizeof(struct free_ptr_struct)];
00168   } ptr;
00169   
00170 } block_header_t;
00171 
00172 /* first level index array */
00173 typedef struct fl_array_struct {
00174   /* ptr is pointer to next level */
00175   block_header_t **sl_array;
00176   
00177   /* bitmapSL is the second level bitmap */
00178   __u32 bitmapSL;
00179 } fl_array_t;
00180 
00181 /* 
00182  * When the user calls init_memory_pool, he must give a block of memory
00183  * block, this block will be used to store the TLSF structure
00184  */
00185 
00186 typedef struct TLSF_struct {
00187   __u32 magic_number;
00188   /* 
00189    * max_fl_index, max_sl_index and max_sl_log2_index
00190    * must be __u8 but the compiler assigns 32 bits by efficiency, 
00191    * we also do that
00192    */
00193   __u32 max_fl_index;
00194   __u32 max_fl_pow2_index;
00195   __u32 max_sl_index;
00196   __u32 max_sl_log2_index;
00197   /* bitmapFL is the bitmap of the first level */
00198   __u32 bitmapFL;
00199   /* first_bh will be our first memory block allocated by MALLOC function */
00200   block_header_t *first_bh;
00201 
00202   /* 
00203    * fl_array will be our first level array,
00204    * it will be an array of [max_fl_index] elements
00205    */
00206   fl_array_t *fl_array;
00207 } TLSF_t;
00208 
00209 /*
00210  * header_overhead has size of blocks_header - 2 * ptr to next free block
00211  */
00212 static __s32 beg_header_overhead = 0;
00213 
00214 #define TLSF__set_bit(num, mem) mem |= (1 << num)
00215 #define TLSF__clear_bit(num, mem) mem &= ~(1 << num)
00216 
00217 char *main_buffer = NULL;
00218 
00219 /*
00220  * log2size ()  returns cell  of log2 (len)  it does a  search between
00221  * MIN_SIZE and MAX_SIZE values in order to find the log2 of the size.
00222  * Theorically  we have obtained  that this  method is  more efficient
00223  * than the asm instruction which does the same operation
00224  */
00225 
00226 static inline __s32 log2size (size_t size, size_t *new_size) {
00227   
00228   __s32 i;
00229 
00230   /* Other way quicker and also more machine dependent that the first one */
00231   /*------------------------------*/
00232   i = TLSF_fls(size);
00233   
00234     
00235   *new_size = (1 << i);
00236 
00237   return i;
00238 }
00239 
00240 /*
00241  * mapping_function () returns first and second level index
00242  *
00243  * first level index function is:
00244  * fl = log2 (size)
00245  *
00246  * and second level index function is:
00247  * sl = (size - 2**(log2size (size))) / (log2 (size) - log2 (MAX_SL_INDEX))
00248  *
00249  */
00250 
00251 static inline __s32 mapping_function (size_t size, __s32 *fl, __s32 *sl,
00252                                       TLSF_t *ptr_TLSF){
00253   __s32 aux, new_len;
00254    
00255   /* This is a new way to calculate first level index 
00256      and second level index, it is quicker than older one */
00257   
00258   *fl = log2size (size, &new_len);
00259   aux = (*fl - ptr_TLSF -> max_sl_log2_index);
00260   *sl = ((size ^ new_len) >> aux);
00261   
00262   return 0;
00263 }
00264 
00265 /* 
00266    Max_size is in Kbytes, On success this function returns the free size
00267  */
00268 
00269 
00270 int init_memory_pool (int max_size,
00271                       int max_sl_log2_index, char *block_ptr) {
00272   __s32 n, free_mem = 0, total_size;
00273   block_header_t *initial_block_ptr;
00274   __s32 size_fl_sl_array, i, fl, sl;
00275   TLSF_t *ptr_TLSF;
00276   
00277   if (!(max_size > 0)) {
00278     PRINT_MSG ("ERROR: size must be > 0\n");
00279     return -1;
00280   }
00281   
00282   if (max_sl_log2_index > 5 || max_sl_log2_index < 1) {
00283     PRINT_MSG ("ERROR max_sl_log2_index must be >=1 or <= 5\n");
00284     return -1;
00285   }
00286   
00287   if (max_sl_log2_index <= 0) {
00288     PRINT_MSG ("ERROR: max_sl_log2_index (%d) must be >= 0\n", 
00289                max_sl_log2_index);
00290     return -1;
00291   }
00292 
00293   if ((((__u32) block_ptr >> LOG2_TLSF_WORD_SIZE) << LOG2_TLSF_WORD_SIZE) 
00294       != (__u32) block_ptr) {
00295     PRINT_MSG ("ERROR block_ptr must be aligned\n");
00296     return -1;
00297   }
00298   
00299   memset ((char *) block_ptr, 0x00, max_size * 1024);
00300 
00301   INIT_THREAD_MUTEX();
00302   ptr_TLSF = (TLSF_t *) block_ptr;
00303   
00304   ptr_TLSF -> magic_number = MAGIC_NUMBER;
00305   
00306   /* Total size of the block, TLSF_struct + free_memory */
00307   
00308   total_size = BYTES2TLSF_WORDS(max_size * 1024);
00309 
00310   ptr_TLSF -> max_sl_log2_index = max_sl_log2_index;
00311   ptr_TLSF -> max_sl_index = (1 << ptr_TLSF -> max_sl_log2_index);
00312   
00313   size_fl_sl_array = BYTES2TLSF_WORDS((__s32) sizeof (fl_array_t) +
00314     ((__s32) sizeof (block_header_t *) * (__s32) ptr_TLSF -> max_sl_index));
00315 
00316   free_mem = total_size - BYTES2TLSF_WORDS(sizeof (TLSF_t)) - size_fl_sl_array;
00317     
00318   n = MIN_LOG2_SIZE + 1;
00319   
00320   while ((int) TLSF_WORDS2BYTES(free_mem) > 
00321          (1 << (n + LOG2_TLSF_WORD_SIZE)) && n < MAX_FL_INDEX) {
00322     n ++;
00323     free_mem -= size_fl_sl_array;
00324   }
00325   
00326   if (free_mem < 0) return -1;
00327 
00328   // max_fl_index never will be greater than 32 (4 Gbytes)
00329   
00330   ptr_TLSF -> max_fl_index = n;
00331   ptr_TLSF -> max_fl_pow2_index = (1 << ptr_TLSF -> max_fl_index);
00332   
00333   n -= MIN_LOG2_SIZE;
00334   
00335   /* max_fl_index will never be greater than MAX_FL_INDEX */
00336   if (ptr_TLSF -> max_fl_index < 0 || MAX_FL_INDEX < 0) return -1;
00337   
00338   ptr_TLSF -> fl_array = ( fl_array_t *) 
00339     ((__u32) &(ptr_TLSF -> fl_array) 
00340      + (__u32) sizeof (ptr_TLSF -> fl_array));
00341   
00342   for (i = 0 ; i < n; i ++)
00343     ptr_TLSF -> fl_array [i] .sl_array = (block_header_t **) 
00344       (((__s32) ptr_TLSF -> fl_array + ((__s32) sizeof (fl_array_t) * n)) +
00345        ((__s32) sizeof (block_header_t *) *
00346         (__s32) ptr_TLSF -> max_sl_index * i));
00347   
00348   initial_block_ptr = (block_header_t *) 
00349     ((__u32) ptr_TLSF -> fl_array + 
00350      (TLSF_WORDS2BYTES(size_fl_sl_array) * n));
00351   
00352   ptr_TLSF -> first_bh = initial_block_ptr;
00353   
00354   beg_header_overhead = BYTES2TLSF_WORDS((int) initial_block_ptr -> ptr.buffer
00355                                          - (int) initial_block_ptr);
00356 
00357   ptr_TLSF -> bitmapFL = 0;
00358  
00359   
00360   initial_block_ptr -> size =
00361     free_mem - beg_header_overhead;
00362 
00363   SET_LAST_BLOCK (initial_block_ptr);
00364 
00365   initial_block_ptr -> ptr.free_ptr.prev = NULL;
00366   initial_block_ptr -> ptr.free_ptr.next = NULL;
00367   initial_block_ptr -> prev_phys_block = NULL;
00368   
00369   if (TLSF_WORDS2BYTES(GET_BLOCK_SIZE(initial_block_ptr)) 
00370       <= MIN_SIZE) {
00371     return -1;
00372   } else {
00373     mapping_function (GET_BLOCK_SIZE(initial_block_ptr), &fl, &sl, 
00374                       ptr_TLSF);
00375     fl -= MIN_LOG2_SIZE;
00376   }
00377 
00378   ptr_TLSF -> fl_array [fl].sl_array [sl] = initial_block_ptr;
00379   TLSF__set_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00380   TLSF__set_bit (fl, ptr_TLSF -> bitmapFL);
00381   
00382   return TLSF_WORDS2BYTES(GET_BLOCK_SIZE(initial_block_ptr));
00383 }
00384 
00385 void destroy_memory_pool (char *block_ptr) {
00386   TLSF_t *ptr_TLSF;
00387   ptr_TLSF = (TLSF_t *) block_ptr;
00388   ptr_TLSF -> magic_number = 0;
00389 } 
00390 
00391 /* see man malloc */
00392 /*
00393  * malloc searchs a free block of size 'size',
00394  * after the free block will be splitted in two new blocks,
00395  * one of these new blocks will be given to the user and the
00396  * other will be inserted into TLSF structure
00397  *
00398  * The cost of this operation is
00399  *      best case: (K) = (1)
00400  *      worst case: (MAX_FL_LOG2_INDEX - MIN_FL_LOG2_INDEX + MAX_SL_INDEX + K)
00401  *                   = (1)
00402  * where K is a constant integer
00403  */
00404 
00405 #ifdef WITH_RTL_PREFIX
00406 void *rtl_malloc_ex (size_t size, char *block_ptr) {
00407 #else
00408 void *malloc_ex (size_t size, char *block_ptr) {
00409 #endif
00410   TLSF_t *ptr_TLSF;
00411   int fl, sl, n, found = 0, old_size = BYTES2TLSF_WORDS(size), last_block;
00412   block_header_t *bh = NULL, *bh2 = NULL, *bh3 = NULL;
00413   
00414   ptr_TLSF = (TLSF_t *) block_ptr;
00415 
00416   if (ptr_TLSF == NULL || ptr_TLSF -> magic_number != MAGIC_NUMBER) {
00417     PRINT_MSG ("FATAL ERROR: TLSF structure not initialized\n");
00418     return NULL;
00419   }
00420 
00421   if (!(size > 0)) {
00422     PRINT_MSG ("ERROR: Memory pool exhausted!!!\n");
00423     return NULL;
00424   }
00425 
00426   if (old_size < MIN_SIZE) {
00427     size = MIN_SIZE;
00428     fl = 0;
00429     sl = 0;
00430   } else {
00431     mapping_function (old_size, &fl, &sl, ptr_TLSF);
00432 
00433     if (++sl == ptr_TLSF -> max_sl_index) {
00434       fl ++;
00435       sl = 0;
00436     }
00437     
00438     /*
00439      * This is the reason of the internal fragmentation
00440      * The block given is greater that the size demanded
00441      */
00442     
00443     /* size can be smaller that maximum SLI, in this case the mapping function
00444        has problems calculating fl and sl values */
00445  
00446     if (old_size >= 
00447         BYTES2TLSF_WORDS(ptr_TLSF -> max_sl_index << 2)) {
00448       size = (1 << fl);
00449       size += (sl << (fl - ptr_TLSF -> max_sl_log2_index));
00450     } else {
00451       size = old_size + 1;
00452       sl = old_size - MIN_SIZE;
00453     }
00454     
00455     fl -= MIN_LOG2_SIZE;
00456   }
00457 
00458 
00459   /*----------------------------------------*/
00460   /* The search for a free block begins now */
00461   /*----------------------------------------*/
00462   
00463   /*
00464    * Our first try, we take the first free block 
00465    * from fl_array or its buddy
00466    */
00467   
00468   THREAD_LOCK();
00469   sl = ptr_TLSF -> fl_array[fl].bitmapSL & ((~0) << sl);
00470   if (sl != 0) {
00471     sl = TLSF_fls(sl);
00472     bh =  ptr_TLSF -> fl_array [fl].sl_array [sl];
00473     ptr_TLSF -> fl_array [fl].sl_array [sl] = bh -> ptr.free_ptr.next;
00474     if (ptr_TLSF -> fl_array [fl].sl_array [sl] != NULL)
00475       ptr_TLSF ->fl_array [fl].sl_array [sl] -> ptr.free_ptr.prev = NULL;
00476     else {
00477       TLSF__clear_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00478       if (!ptr_TLSF -> fl_array[fl].bitmapSL)
00479         TLSF__clear_bit (fl, ptr_TLSF -> bitmapFL);
00480     }
00481     found = 1;
00482     goto out;
00483   }
00484   
00485   /*
00486    * On the last case a free block is searched using a bitmap
00487    */
00488   
00489   fl = TLSF_fls(ptr_TLSF -> bitmapFL & ((~0) << (fl + 1)));
00490   
00491   if (fl > 0) {
00492     sl = TLSF_fls(ptr_TLSF -> fl_array[fl].bitmapSL);
00493     bh = ptr_TLSF -> fl_array [fl].sl_array [sl];
00494     ptr_TLSF -> fl_array [fl].sl_array [sl] = bh -> ptr.free_ptr.next;
00495     if (ptr_TLSF -> fl_array [fl].sl_array [sl] != NULL){
00496       ptr_TLSF -> fl_array [fl].sl_array [sl] 
00497         -> ptr.free_ptr.prev = NULL;
00498     } else {
00499       TLSF__clear_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00500       if (!ptr_TLSF -> fl_array[fl].bitmapSL)
00501         TLSF__clear_bit (fl, ptr_TLSF -> bitmapFL);
00502     }
00503     found = 1;
00504     goto out;
00505   }
00506   /* end of the search */
00507   /*------------------------------------------------------------*/
00508   
00509  out:
00510   
00511   /*
00512    * HUGGGG, NOT ENOUGHT MEMORY
00513    * I think that we have done all that we have been able, I'm sorry
00514    */
00515   
00516   if (!found) {
00517     THREAD_UNLOCK();
00518     PRINT_MSG ("ERROR: Memory pool exhausted!!!\n");
00519     return NULL;
00520   }
00521   
00522   /*
00523    * we can say: YESSSSSSSSSSS, we have enought memory!!!!
00524    */
00525   
00526   /* can bh be splitted? */ 
00527   
00528   n = (int)(GET_BLOCK_SIZE(bh) - size - beg_header_overhead);
00529   if (n >= (int) MIN_SIZE) {
00530     /*
00531      * Yes, bh will be splitted
00532      */
00533 
00534     /* The new block will begin at the end of the current block */
00535     last_block = IS_LAST_BLOCK(bh)?1:0;
00536     bh -> size = size;
00537     SET_USED_BLOCK(bh);
00538     
00539     bh2 = (block_header_t *) (__u8 *) (bh -> ptr.buffer + 
00540                                        TLSF_WORDS2BYTES
00541                                        (GET_BLOCK_SIZE(bh)));
00542     bh2 -> prev_phys_block = bh;
00543     bh2 -> size = n;
00544     if (last_block) SET_LAST_BLOCK (bh2);
00545     mapping_function (GET_BLOCK_SIZE(bh2), &fl, &sl, ptr_TLSF);
00546     fl -= MIN_LOG2_SIZE;
00547     bh2 -> ptr.free_ptr.first_index = fl;
00548     bh2 -> ptr.free_ptr.second_index = sl;
00549     bh2 -> ptr.free_ptr.prev = NULL;
00550     bh2 -> ptr.free_ptr.next = ptr_TLSF -> fl_array [fl].sl_array [sl];
00551     
00552     if (!IS_LAST_BLOCK (bh2)) {
00553       bh3 = (block_header_t *) (__u8 *) (bh2 -> ptr.buffer + 
00554                                          TLSF_WORDS2BYTES
00555                                          (GET_BLOCK_SIZE(bh2)));
00556       bh3 -> prev_phys_block = bh2;
00557     }
00558     
00559 
00560     if (ptr_TLSF -> fl_array [fl].sl_array [sl] != NULL)
00561       ptr_TLSF -> fl_array [fl].sl_array [sl] -> ptr.free_ptr.prev = bh2;
00562     ptr_TLSF -> fl_array [fl].sl_array [sl] = bh2;
00563     TLSF__set_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00564     TLSF__set_bit (fl, ptr_TLSF -> bitmapFL); 
00565   }
00566   
00567   SET_USED_BLOCK(bh);
00568 
00569   THREAD_UNLOCK();
00570   
00571   return (void *)  bh -> ptr.buffer; 
00572 }
00573 
00574 /*
00575  * see man free
00576  *
00577  * free () is only guaranteed  to work if ptr is the address
00578  * of a block allocated by rt_malloc() (and not yet freed).
00579  */
00580  
00581 #ifdef WITH_RTL_PREFIX
00582 void rtl_free_ex (void *ptr, char *block_ptr) {
00583 #else
00584 void free_ex (void *ptr, char *block_ptr) {
00585 #endif
00586   int fl, sl;
00587   block_header_t *bh = NULL, *bh2 = NULL, *bh3;
00588 
00589   TLSF_t *ptr_TLSF;
00590 
00591   ptr_TLSF = (TLSF_t *) block_ptr;
00592 
00593   if (ptr_TLSF == NULL || ptr_TLSF -> magic_number != MAGIC_NUMBER) {
00594     PRINT_MSG ("FATAL ERROR: TLSF structure not initialized\n");
00595     return;
00596   }
00597 
00598   bh = (block_header_t *) ((__u8 *) ptr - 
00599                            TLSF_WORDS2BYTES(beg_header_overhead));
00600  
00601   THREAD_LOCK();
00602   /* now bh is a free block */
00603   
00604   SET_FREE_BLOCK (bh);
00605   bh -> ptr.free_ptr.prev = NULL;
00606   bh -> ptr.free_ptr.next = NULL;
00607 
00608   /*
00609    * first of all, we will try to merge bh with the
00610    * physically contiguos free block and
00611    * after we will inserte bh into TLSF structure
00612    */
00613 
00614   /* Now we will try if we can merge bh with the next phys. contiguos block */
00615   if (!IS_LAST_BLOCK (bh)) {
00616     /* is it the next block free? */
00617     /* The next block is easy to found */
00618     
00619     bh2 = (block_header_t *) (__u8 *) (bh -> ptr.buffer + 
00620                                        TLSF_WORDS2BYTES
00621                                        (GET_BLOCK_SIZE(bh)));
00622     if (!IS_USED_BLOCK (bh2)) {
00623       /* we are lucky, we can merge bh with the following one */  
00624       if (bh2 -> ptr.free_ptr.next != NULL)
00625         bh2 -> ptr.free_ptr.next -> ptr.free_ptr.prev =
00626           bh2  -> ptr.free_ptr.prev;
00627       
00628       if (bh2 -> ptr.free_ptr.prev != NULL)
00629         bh2 -> ptr.free_ptr.prev -> ptr.free_ptr.next =
00630           bh2 -> ptr.free_ptr.next;
00631       
00632       fl = bh2 -> ptr.free_ptr.first_index;
00633       sl = bh2 -> ptr.free_ptr.second_index;
00634       
00635       /* bh2 must be deleted from fl_array */
00636       if (ptr_TLSF -> fl_array [fl].sl_array [sl] == bh2)
00637         ptr_TLSF -> fl_array [fl].sl_array [sl] = bh2 -> ptr.free_ptr.next;
00638       
00639       if (ptr_TLSF -> fl_array [fl].sl_array [sl] == NULL){
00640         TLSF__clear_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00641         if (!ptr_TLSF -> fl_array[fl].bitmapSL) 
00642           TLSF__clear_bit (fl, ptr_TLSF -> bitmapFL);
00643         
00644       }
00645 
00646       bh -> size += bh2 -> size + beg_header_overhead;
00647       if (!IS_LAST_BLOCK (bh2)) {
00648         bh3 = (block_header_t *) (__u8 *) (bh2 -> ptr.buffer + 
00649                                            TLSF_WORDS2BYTES
00650                                            (GET_BLOCK_SIZE(bh2)));
00651         bh3 -> prev_phys_block = bh;
00652       }
00653       
00654       if (IS_LAST_BLOCK (bh2)) SET_LAST_BLOCK (bh);
00655     }
00656   }
00657 
00658   /* is it free the previous physical block? */
00659   if (bh -> prev_phys_block != NULL) { // This block is not the first block
00660    
00661     bh2 = bh -> prev_phys_block;
00662   
00663     if (!IS_USED_BLOCK (bh2)) {
00664 
00665       if (bh2 -> ptr.free_ptr.next != NULL)
00666         bh2 -> ptr.free_ptr.next -> ptr.free_ptr.prev =
00667           bh2  -> ptr.free_ptr.prev;
00668       
00669       if (bh2 -> ptr.free_ptr.prev != NULL)
00670         bh2 -> ptr.free_ptr.prev -> ptr.free_ptr.next =
00671           bh2 -> ptr.free_ptr.next;
00672       
00673       fl = bh2 -> ptr.free_ptr.first_index;
00674       sl = bh2 -> ptr.free_ptr.second_index;
00675         
00676       if (ptr_TLSF -> fl_array [fl].sl_array [sl] == bh2)
00677         ptr_TLSF -> fl_array [fl].sl_array [sl] = bh2 -> ptr.free_ptr.next;
00678       
00679       if (ptr_TLSF -> fl_array[fl].sl_array[sl] == NULL){
00680         
00681         TLSF__clear_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00682         if (!ptr_TLSF -> fl_array[fl].bitmapSL)
00683           TLSF__clear_bit (fl, ptr_TLSF -> bitmapFL);
00684         
00685       }     
00686       bh2 -> size += bh -> size + beg_header_overhead;
00687 
00688       bh = bh2;
00689       if (!IS_LAST_BLOCK (bh)) {
00690         bh3 = (block_header_t *) (__u8 *) (bh -> ptr.buffer + 
00691                                            TLSF_WORDS2BYTES
00692                                            (GET_BLOCK_SIZE(bh)));
00693         bh3 -> prev_phys_block = bh;
00694       }
00695     
00696     }
00697  
00698   }
00699 
00700   /*
00701    * and now we can merge the free block with the initial memory
00702    */
00703   mapping_function (GET_BLOCK_SIZE (bh), &fl, &sl, ptr_TLSF);
00704   fl -= MIN_LOG2_SIZE;
00705   bh -> ptr.free_ptr.first_index = fl;
00706   bh -> ptr.free_ptr.second_index = sl;
00707   bh -> ptr.free_ptr.next = ptr_TLSF -> fl_array [fl].sl_array [sl];
00708   bh -> ptr.free_ptr.prev = NULL;
00709  
00710   if (ptr_TLSF -> fl_array [fl].sl_array [sl] != NULL)
00711     ptr_TLSF -> fl_array [fl].sl_array [sl] -> ptr.free_ptr.prev = bh;
00712   ptr_TLSF -> fl_array [fl].sl_array [sl] = bh;
00713 
00714   TLSF__set_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);
00715   TLSF__set_bit (fl, ptr_TLSF -> bitmapFL);    
00716   THREAD_UNLOCK();
00717 }
00718 
00719 /* see man realloc */
00720 #ifdef WITH_RTL_PREFIX
00721 void *rtl_realloc_ex (void *p, size_t new_len, char *block_ptr) {
00722 #else
00723 void *realloc_ex (void *p, size_t new_len, char *block_ptr) {
00724 #endif
00725   __u8 *ptr_aux;
00726   block_header_t *b;
00727 
00728   if (p == NULL)
00729 #ifdef WITH_RTL_PREFIX
00730     return (void *) rtl_malloc_ex (new_len, block_ptr);
00731 #else
00732     return (void *) malloc_ex (new_len, block_ptr);
00733 #endif
00734   else if (new_len == 0) {
00735 #ifdef WITH_RTL_PREFIX
00736     rtl_free_ex (p, block_ptr);
00737 #else
00738     free_ex (p, block_ptr);
00739 #endif
00740     return NULL;
00741   }
00742 
00743 #ifdef WITH_RTL_PREFIX  
00744   ptr_aux = (__u8 *) rtl_malloc_ex (new_len * sizeof (__u8), block_ptr);
00745 #else
00746   ptr_aux = (__u8 *) malloc_ex (new_len * sizeof (__u8), block_ptr);
00747 #endif
00748   
00749   b = (block_header_t *) (((__u8 *) p) - 
00750                           TLSF_WORDS2BYTES(beg_header_overhead));
00751 
00752   memcpy ((__u8 *) ptr_aux, (__u8 *) b, b -> size);
00753 #ifdef WITH_RTL_PREFIX
00754   rtl_free_ex (p, block_ptr);
00755 #else
00756   free_ex (p, block_ptr);
00757 #endif
00758 
00759   return ((void *) ptr_aux);
00760 }
00761 
00762 /* see man calloc */
00763 #ifdef WITH_RTL_PREFIX
00764 void *rtl_calloc_ex (size_t nelem, size_t elem_size, char *block_ptr) {
00765 #else
00766 void *calloc_ex (size_t nelem, size_t elem_size, char *block_ptr) {
00767 #endif
00768 
00769   __u8 *p;
00770 
00771   if (nelem <= 0 || elem_size <= 0) return NULL;
00772 
00773 #ifdef WITH_RTL_PREFIX
00774   if ((p = (__u8 *) rtl_malloc_ex (nelem * elem_size, block_ptr)) == NULL)
00775     return NULL;
00776 #else
00777   if ((p = (__u8 *) malloc_ex (nelem * elem_size, block_ptr)) == NULL )
00778     return NULL;
00779 #endif
00780 
00781   memset (p, 0, nelem * elem_size);
00782   
00783   return ((void *) p);
00784 }
00785 
00786 static void print_block (block_header_t *b){
00787   if (b == NULL) return;
00788 
00789   PRINT_DBG_C (">>>> Address 0x");
00790   PRINT_DBG_H (b);
00791   
00792   if ((b -> size & USED_BLOCK) != USED_BLOCK)
00793     PRINT_DBG_C ("\n>>>> Status FREE");
00794   else
00795     PRINT_DBG_C ("\n>>>> Status USED");
00796   
00797   PRINT_DBG_C (" Block Size ");
00798   PRINT_DBG_D (TLSF_WORDS2BYTES(b -> size));
00799   PRINT_DBG_C (" bytes");
00800   
00801   if (b -> prev_phys_block == NULL)
00802     PRINT_DBG_C ("\n>>>> FIRST BLOCK");
00803   else {
00804     PRINT_DBG_C ("\n>>>> PREV. PHYS. BLOCK 0x");
00805     PRINT_DBG_H (b -> prev_phys_block);
00806   }
00807 
00808   if ((b -> size & LAST_BLOCK) == LAST_BLOCK)
00809     PRINT_DBG_C (" LAST BLOCK");
00810   else
00811     PRINT_DBG_C (" NOT LAST BLOCK");
00812   
00813   if ((b -> size & FREE_BLOCK) == FREE_BLOCK){
00814     PRINT_DBG_C ("\n---- Prev Free 0x");
00815     PRINT_DBG_H (b -> ptr.free_ptr.prev);
00816     PRINT_DBG_C (" Next Free 0x");
00817     PRINT_DBG_H (b -> ptr.free_ptr.next);
00818   }
00819   PRINT_DBG_C ("\n\n");
00820 }
00821 
00822 /*
00823  * structure_status () shows the status of all the blocks
00824  */
00825 void structure_status (char *block_ptr) {
00826   block_header_t *b;
00827   TLSF_t *ptr_TLSF;
00828   int end = 0;
00829   
00830   ptr_TLSF = (TLSF_t *) block_ptr; 
00831   if (ptr_TLSF == NULL || ptr_TLSF -> magic_number != MAGIC_NUMBER) {
00832     PRINT_MSG ("FATAL ERROR: TLSF structure not initialized\n");
00833     return;
00834   }
00835  
00836   b = ptr_TLSF -> first_bh;
00837   PRINT_DBG_C ("\nTLSF structure address 0x");
00838   PRINT_DBG_H (ptr_TLSF);
00839   PRINT_DBG_C ("\nMax. first level index: ");
00840   PRINT_DBG_D (ptr_TLSF -> max_fl_index);
00841   PRINT_DBG_C ("\nMax. second level index: ");
00842   PRINT_DBG_D (ptr_TLSF -> max_sl_log2_index);
00843   PRINT_DBG_C ("\n\nALL BLOCKS\n");
00844   while (!end) {
00845     print_block (b);
00846     if (IS_LAST_BLOCK(b))
00847       end = 1;
00848     else
00849       b = (block_header_t *) (__u8 *) (b -> ptr.buffer + 
00850                                        TLSF_WORDS2BYTES
00851                                        (GET_BLOCK_SIZE(b)));
00852   }
00853 
00854 }
00855 
00856 /*
00857  * free_blocks_status () only shows the status
00858  * of the free blocks
00859  */
00860 void free_blocks_status (char *block_ptr){
00861   int i, j;
00862   block_header_t *b;
00863 
00864   TLSF_t *ptr_TLSF;
00865   
00866   ptr_TLSF = (TLSF_t *) block_ptr; 
00867   if (ptr_TLSF == NULL || ptr_TLSF -> magic_number != MAGIC_NUMBER) {
00868     PRINT_MSG ("FATAL ERROR: TLSF structure not initialized\n");
00869     return;
00870   }
00871 
00872   PRINT_DBG_C ("\nTLSF structure address 0x");
00873   PRINT_DBG_H (ptr_TLSF);
00874   PRINT_DBG_C ("\nFREE BLOCKS\n\n");
00875   for (i = ptr_TLSF -> max_fl_index  - 1 - MIN_LOG2_SIZE; i >= 0; i--) {
00876     if (ptr_TLSF -> fl_array [i].bitmapSL > 0)
00877       for (j = ptr_TLSF -> max_sl_index - 1; j >= 0; j--) {
00878         if (ptr_TLSF -> fl_array [i].sl_array[j] != NULL) {
00879           b = ptr_TLSF -> fl_array [i].sl_array [j];
00880           PRINT_DBG_C ("[");
00881           PRINT_DBG_D (i + MIN_LOG2_SIZE);
00882           PRINT_DBG_C ("] ");
00883           PRINT_DBG_D (TLSF_WORDS2BYTES(1 << (i + MIN_LOG2_SIZE)));
00884           PRINT_DBG_C (" bytes -> Free blocks: 0x");
00885           PRINT_DBG_H (ptr_TLSF -> fl_array [i].bitmapSL);
00886           PRINT_DBG_C ("\n");
00887           
00888           while (b != NULL) {
00889             PRINT_DBG_C (">>>> First_Level [");
00890             PRINT_DBG_D (i + MIN_LOG2_SIZE);
00891             PRINT_DBG_C ("] Second Level [");
00892             PRINT_DBG_D (j);
00893             PRINT_DBG_C ("] -> ");
00894             PRINT_DBG_D (TLSF_WORDS2BYTES((1 << (i + MIN_LOG2_SIZE)) + 
00895                           ( ((1 << (i + MIN_LOG2_SIZE)) / 
00896                              ptr_TLSF -> max_sl_index) * j)));
00897 
00898             PRINT_DBG_C (" bytes\n");
00899             print_block (b);
00900             b = b -> ptr.free_ptr.next;
00901           }
00902         }
00903       }
00904   }
00905 }
00906 
00907 void dump_memory_region (unsigned char *mem_ptr, unsigned int size) {
00908   
00909   unsigned int begin = (unsigned int) mem_ptr;
00910   unsigned int end = (unsigned int) 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_DBG_C ("\nMemory region dumped: 0x");
00921   PRINT_DBG_H (begin);
00922   PRINT_DBG_C (" - ");
00923   PRINT_DBG_H (end);
00924   PRINT_DBG_C ("\n\n");
00925   
00926   column = 0;
00927   PRINT_DBG_C ("\t\t+0");
00928   PRINT_DBG_C ("\t+1");
00929   PRINT_DBG_C ("\t+2");
00930   PRINT_DBG_C ("\t+3");
00931   PRINT_DBG_C ("\t+4");
00932   PRINT_DBG_C ("\t+5");
00933   PRINT_DBG_C ("\n0x");
00934   PRINT_DBG_H (begin);
00935   PRINT_DBG_C ("\t");
00936 
00937   while (begin < end) {
00938     if (((unsigned char *) begin) [0] == 0)
00939       PRINT_DBG_C ("00");
00940     else
00941       PRINT_DBG_H (((unsigned char *) begin) [0]);
00942     if (((unsigned char *) begin) [1] == 0)
00943       PRINT_DBG_C ("00");
00944     else
00945       PRINT_DBG_H (((unsigned char *) begin) [1]);
00946     PRINT_DBG_C ("\t");
00947     begin += 2;
00948     column ++;
00949     if (column == 6) {
00950       PRINT_DBG_C ("\n0x");
00951       PRINT_DBG_H (begin);
00952       PRINT_DBG_C ("\t");
00953       column = 0;
00954     }
00955 
00956   }
00957   PRINT_DBG_C ("\n\n"); 
00958 }
00959  

Generated on Wed Jan 14 12:58:57 2004 for RTL-lwIP-0.4 by doxygen 1.3.4