⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl_malloc.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Two Levels Segregate Fit memory allocator (TLSF) * Version 1.1 * * Written by Miguel Masmano Tello <mmasmano@disca.upv.es> * Copyright (C) Dec, 2002 OCERA Consortium * Release under the terms of the GNU General Public License Version 2 * */#include "rtl_malloc.h"#include <arch/bits.h>// linux/types.h includes definitions// for the standard types// #include <linux/types.h>#if !defined (__RTL__) && defined (__KERNEL__)#error "This modules can only be used by RTLinux or by user space"#endif#if defined (__RTL__)#include <linux/config.h>#define INIT_THREAD_MUTEX()#define THREAD_LOCK() __asm__ __volatile__ ("cli");#define THREAD_UNLOCK() __asm__ __volatile__ ("sti");MODULE_AUTHOR("Miguel Masmano Tello <mmasmano@disca.upv.es>");MODULE_DESCRIPTION("Three Levels Segregate Fit memory allocator (TLSF) V1.0");MODULE_LICENSE("GPL");static int max_size = 1024; // 1 MByteMODULE_PARM(max_size, "i");MODULE_PARM_DESC(max_size, "Memory pool size in Kb (default=1024)");static unsigned char *ptr_mem;/* This TLSF version only can be used with BIGPHYSAREA patch */#if defined(CONFIG_BIGPHYSAREA) || defined(CONFIG_BIGPHYS_AREA)#include <linux/bigphysarea.h>#else#error BIGPHYSAREA LINUX KERNEL PATCH MUST BE INSTALLED#endifint init_module(void){  // First of all we reserve the memory that will be used later  ptr_mem = (unsigned char *) bigphysarea_alloc(max_size * 1024);  if (ptr_mem == NULL) {     rtl_printf ("rtl_malloc PANIC: Error reserving memory!!");    return -1;   }  if (init_memory_pool (max_size, 5, ptr_mem) < 0) return -1;  associate_buffer (ptr_mem);    return 0;}void cleanup_module(void){  destroy_memory_pool(ptr_mem);  bigphysarea_free((caddr_t) ptr_mem, 0);}#else // #if defined (__RTL__)#define INIT_THREAD_MUTEX()#define THREAD_LOCK()#define THREAD_UNLOCK()#endif // #if defined (__RTL__)/* * The following  TAD will be a  double level indexed  array, the most * important thing is that the time  is bounded, the reason of this is * because TLSF has been designed to be used by real time programs. * *     First level       Second level *     it is indexed     it is indexed by 2**n+(2**n/m*index_number) *     by power of 2 *                            0             1     m-1        m *                            ----> NULL   --> NULL          ----> NUL *                            |            |                 | *       -------         ---------------------...--------------------- *  2**n |  n  |  -----> |2**n+(2**n/m*0)|...|   |...|2**n+(2**n/m*m)| *       |-----|         ---------------------...--------------------- * 2**n-1| n-1 |  -----> ....                      | *       |-----|                                   --->NULL *        ..... *//*  * Some defaults values; * please, don't touch these macros */#define TLSF_WORD_SIZE 4 //(sizeof(__u32))#define LOG2_TLSF_WORD_SIZE 2 //(TLSF_fls(TLSF_WORD_SIZE)) // TLSF_WORD size#define MIN_LOG2_SIZE 2 // 16 bytes#define MIN_SIZE 4 //(1 << MIN_LOG2_SIZE)#define TLSF_WORDS2BYTES(x) ((x) << LOG2_TLSF_WORD_SIZE)#define BYTES2TLSF_WORDS(x) ((x) >> LOG2_TLSF_WORD_SIZE)/*  * The following structure defines the pointers used  * by the header to know the position of the free blocks  */typedef struct free_ptr_struct {  struct block_header_struct *prev;  struct block_header_struct *next;  /*    * first_index and second_index are used to store   * mapping_function results, that's how we get some extra   * nanoseconds    */  __u8 first_index;  __u8 second_index;} free_ptr_t;/* * USED_BLOCK must be used like mask with the magic number * i.e.  * if ((magic_number & USED_BLOCK) = USED_BLOCK) then *   return USED; * else *   return FREE * end if; */#define USED_BLOCK 0x80000000#define FREE_BLOCK ~USED_BLOCK //0x7FFFFFFF#define LAST_BLOCK 0x40000000#define NOT_LAST_BLOCK ~LAST_BLOCK //0xBFFFFFFF#define IS_USED_BLOCK(x) ((x -> size & USED_BLOCK) == USED_BLOCK)#define IS_LAST_BLOCK(x) ((x -> size & LAST_BLOCK) == LAST_BLOCK)#define GET_BLOCK_SIZE(x) (x -> size & FREE_BLOCK & NOT_LAST_BLOCK)#define SET_USED_BLOCK(x) (x -> size |= USED_BLOCK)#define SET_FREE_BLOCK(x) (x -> size &= FREE_BLOCK)#define SET_LAST_BLOCK(x) (x -> size |= LAST_BLOCK)#define SET_NOT_LAST_BLOCK(x) (x -> size &= NOT_LAST_BLOCK)#define MAGIC_NUMBER 0x2A59FA59typedef struct block_header_struct {  /*    * size codifies the block size in TLSF_BYTES and it also codifies if    * the block is used or free    */    __u32 size;    /* The following pointer points to the previous physical block */  struct block_header_struct *prev_phys_block;  union {    struct free_ptr_struct free_ptr;    __u8 buffer[sizeof(struct free_ptr_struct)];  } ptr;  } block_header_t;/* first level index array */typedef struct fl_array_struct {  /* ptr is pointer to next level */  block_header_t **sl_array;    /* bitmapSL is the second level bitmap */  __u32 bitmapSL;} fl_array_t;/*  * When the user calls init_memory_pool, he must give a block of memory * block, this block will be used to store the TLSF structure */typedef struct TLSF_struct {  __u32 magic_number;  /*    * max_fl_index, max_sl_index and max_sl_log2_index   * must be __u8 but the compiler assigns 32 bits by efficiency,    * we also do that   */  __u32 max_fl_index;  __u32 max_fl_pow2_index;  __u32 max_sl_index;  __u32 max_sl_log2_index;  /* bitmapFL is the bitmap of the first level */  __u32 bitmapFL;  /* first_bh will be our first memory block allocated by MALLOC function */  block_header_t *first_bh;  /*    * fl_array will be our first level array,   * it will be an array of [max_fl_index] elements   */  fl_array_t *fl_array;} TLSF_t;/* * header_overhead has size of blocks_header - 2 * ptr to next free block */static __s32 beg_header_overhead = 0;#define TLSF__set_bit(num, mem) mem |= (1 << num)#define TLSF__clear_bit(num, mem) mem &= ~(1 << num)char *main_buffer = NULL;/* * log2size ()  returns cell  of log2 (len)  it does a  search between * MIN_SIZE and MAX_SIZE values in order to find the log2 of the size. * Theorically  we have obtained  that this  method is  more efficient * than the asm instruction which does the same operation */static inline __s32 log2size (size_t size, size_t *new_size) {    __s32 i;  /* Other way quicker and also more machine dependent that the first one */  /*------------------------------*/  i = TLSF_fls(size);        *new_size = (1 << i);  return i;}/* * mapping_function () returns first and second level index * * first level index function is: * fl = log2 (size) * * and second level index function is: * sl = (size - 2**(log2size (size))) / (log2 (size) - log2 (MAX_SL_INDEX)) * */static inline __s32 mapping_function (size_t size, __s32 *fl, __s32 *sl,				      TLSF_t *ptr_TLSF){  __s32 aux, new_len;     /* This is a new way to calculate first level index      and second level index, it is quicker than older one */    *fl = log2size (size, &new_len);  aux = (*fl - ptr_TLSF -> max_sl_log2_index);  *sl = ((size ^ new_len) >> aux);    return 0;}/*    Max_size is in Kbytes, On success this function returns the free size */int init_memory_pool (int max_size,		      int max_sl_log2_index, char *block_ptr) {  __s32 n, free_mem = 0, total_size;  block_header_t *initial_block_ptr;  __s32 size_fl_sl_array, i, fl, sl;  TLSF_t *ptr_TLSF;    if (!(max_size > 0)) {    PRINT_MSG ("ERROR: size must be > 0\n");    return -1;  }    if (max_sl_log2_index > 5 || max_sl_log2_index < 1) {    PRINT_MSG ("ERROR max_sl_log2_index must be >=1 or <= 5\n");    return -1;  }    if (max_sl_log2_index <= 0) {    PRINT_MSG ("ERROR: max_sl_log2_index (%d) must be >= 0\n",   	       max_sl_log2_index);    return -1;  }  if ((((__u32) block_ptr >> LOG2_TLSF_WORD_SIZE) << LOG2_TLSF_WORD_SIZE)       != (__u32) block_ptr) {    PRINT_MSG ("ERROR block_ptr must be aligned\n");    return -1;  }    memset ((char *) block_ptr, 0x00, max_size * 1024);  INIT_THREAD_MUTEX();  ptr_TLSF = (TLSF_t *) block_ptr;    ptr_TLSF -> magic_number = MAGIC_NUMBER;    /* Total size of the block, TLSF_struct + free_memory */    total_size = BYTES2TLSF_WORDS(max_size * 1024);  ptr_TLSF -> max_sl_log2_index = max_sl_log2_index;  ptr_TLSF -> max_sl_index = (1 << ptr_TLSF -> max_sl_log2_index);    size_fl_sl_array = BYTES2TLSF_WORDS((__s32) sizeof (fl_array_t) +    ((__s32) sizeof (block_header_t *) * (__s32) ptr_TLSF -> max_sl_index));  free_mem = total_size - BYTES2TLSF_WORDS(sizeof (TLSF_t)) - size_fl_sl_array;      n = MIN_LOG2_SIZE + 1;    while ((int) TLSF_WORDS2BYTES(free_mem) > 	 (1 << (n + LOG2_TLSF_WORD_SIZE)) && n < MAX_FL_INDEX) {    n ++;    free_mem -= size_fl_sl_array;  }    if (free_mem < 0) return -1;  // max_fl_index never will be greater than 32 (4 Gbytes)    ptr_TLSF -> max_fl_index = n;  ptr_TLSF -> max_fl_pow2_index = (1 << ptr_TLSF -> max_fl_index);    n -= MIN_LOG2_SIZE;    /* max_fl_index will never be greater than MAX_FL_INDEX */  if (ptr_TLSF -> max_fl_index < 0 || MAX_FL_INDEX < 0) return -1;    ptr_TLSF -> fl_array = ( fl_array_t *)     ((__u32) &(ptr_TLSF -> fl_array)      + (__u32) sizeof (ptr_TLSF -> fl_array));    for (i = 0 ; i < n; i ++)    ptr_TLSF -> fl_array [i] .sl_array = (block_header_t **)       (((__s32) ptr_TLSF -> fl_array + ((__s32) sizeof (fl_array_t) * n)) +       ((__s32) sizeof (block_header_t *) *	(__s32) ptr_TLSF -> max_sl_index * i));    initial_block_ptr = (block_header_t *)     ((__u32) ptr_TLSF -> fl_array +      (TLSF_WORDS2BYTES(size_fl_sl_array) * n));    ptr_TLSF -> first_bh = initial_block_ptr;    beg_header_overhead = BYTES2TLSF_WORDS((int) initial_block_ptr -> ptr.buffer					 - (int) initial_block_ptr);  ptr_TLSF -> bitmapFL = 0;     initial_block_ptr -> size =    free_mem - beg_header_overhead;  SET_LAST_BLOCK (initial_block_ptr);  initial_block_ptr -> ptr.free_ptr.prev = NULL;  initial_block_ptr -> ptr.free_ptr.next = NULL;  initial_block_ptr -> prev_phys_block = NULL;    if (TLSF_WORDS2BYTES(GET_BLOCK_SIZE(initial_block_ptr))       <= MIN_SIZE) {    return -1;  } else {    mapping_function (GET_BLOCK_SIZE(initial_block_ptr), &fl, &sl, 		      ptr_TLSF);    fl -= MIN_LOG2_SIZE;  }  ptr_TLSF -> fl_array [fl].sl_array [sl] = initial_block_ptr;  TLSF__set_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);  TLSF__set_bit (fl, ptr_TLSF -> bitmapFL);    return TLSF_WORDS2BYTES(GET_BLOCK_SIZE(initial_block_ptr));}void destroy_memory_pool (char *block_ptr) {  TLSF_t *ptr_TLSF;  ptr_TLSF = (TLSF_t *) block_ptr;  ptr_TLSF -> magic_number = 0;} /* see man malloc *//* * malloc searchs a free block of size 'size', * after the free block will be splitted in two new blocks, * one of these new blocks will be given to the user and the * other will be inserted into TLSF structure * * The cost of this operation is *      best case: (K) = (1) *      worst case: (MAX_FL_LOG2_INDEX - MIN_FL_LOG2_INDEX + MAX_SL_INDEX + K) *                   = (1) * where K is a constant integer */#ifdef WITH_RTL_PREFIXvoid *rtl_malloc_ex (size_t size, char *block_ptr) {#elsevoid *malloc_ex (size_t size, char *block_ptr) {#endif  TLSF_t *ptr_TLSF;  int fl, sl, n, found = 0, old_size = BYTES2TLSF_WORDS(size), last_block;  block_header_t *bh = NULL, *bh2 = NULL, *bh3 = NULL;    ptr_TLSF = (TLSF_t *) block_ptr;  if (ptr_TLSF == NULL || ptr_TLSF -> magic_number != MAGIC_NUMBER) {    PRINT_MSG ("FATAL ERROR: TLSF structure not initialized\n");    return NULL;  }  if (!(size > 0)) {    PRINT_MSG ("ERROR: Memory pool exhausted!!!\n");    return NULL;  }  if (old_size < MIN_SIZE) {    size = MIN_SIZE;    fl = 0;    sl = 0;  } else {    mapping_function (old_size, &fl, &sl, ptr_TLSF);    if (++sl == ptr_TLSF -> max_sl_index) {      fl ++;      sl = 0;    }        /*     * This is the reason of the internal fragmentation     * The block given is greater that the size demanded     */        /* size can be smaller that maximum SLI, in this case the mapping function       has problems calculating fl and sl values */     if (old_size >= 	BYTES2TLSF_WORDS(ptr_TLSF -> max_sl_index << 2)) {      size = (1 << fl);      size += (sl << (fl - ptr_TLSF -> max_sl_log2_index));    } else {      size = old_size + 1;      sl = old_size - MIN_SIZE;    }        fl -= MIN_LOG2_SIZE;  }  /*----------------------------------------*/  /* The search for a free block begins now */  /*----------------------------------------*/    /*   * Our first try, we take the first free block    * from fl_array or its buddy   */    THREAD_LOCK();  sl = ptr_TLSF -> fl_array[fl].bitmapSL & ((~0) << sl);  if (sl != 0) {    sl = TLSF_fls(sl);    bh =  ptr_TLSF -> fl_array [fl].sl_array [sl];    ptr_TLSF -> fl_array [fl].sl_array [sl] = bh -> ptr.free_ptr.next;    if (ptr_TLSF -> fl_array [fl].sl_array [sl] != NULL)      ptr_TLSF ->fl_array [fl].sl_array [sl] -> ptr.free_ptr.prev = NULL;    else {      TLSF__clear_bit (sl, ptr_TLSF -> fl_array[fl].bitmapSL);      if (!ptr_TLSF -> fl_array[fl].bitmapSL)        TLSF__clear_bit (fl, ptr_TLSF -> bitmapFL);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -