- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/modules/ke/src/ke_mem.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024 #include "co_int.h"
    00025 #include "co_bool.h"
    00026 #include "arch.h"
    00027 #include "dbg_assert.h"
    00028
    00029 #include "co_math.h"
    00030 #include "ke_config.h"
    00031 #include "ke_env.h"
    00032 #include "ke_mem.h"
    00033
    00034
    00035 /*
    00036  * DEFINES
    00037  ****************************************************************************************
    00038  */
    00040 #ifdef CFG_RWTL
    00041 #define KE_HEAP_SIZE     NX_HEAP_SIZE/2
    00042 #else
    00043 #define KE_HEAP_SIZE     NX_HEAP_SIZE
    00044 #endif
    00045
    00047 struct mblock_free
    00048 {
    00049     struct mblock_free *next;
    00050     #if CPU_WORD_SIZE == 4
    00051     uint32_t size;
    00052     #elif CPU_WORD_SIZE == 2
    00053     uint16_t size;
    00054     #endif
    00055 };
    00056
    00058 struct mblock_used
    00059 {
    00060     uint32_t size;
    00061 };
    00062
    00063 /*
    00064  * GLOBAL VARIABLES
    00065  ****************************************************************************************
    00066  */
    00068 #ifdef CFG_RWTL
    00069 uint16_t ke_mem_heap[KE_HEAP_SIZE];
    00070 #else
    00071 uint8_t ke_mem_heap[KE_HEAP_SIZE];
    00072 #endif
    00073
    00074 /*
    00075  * FUNCTION DEFINITIONS
    00076  ****************************************************************************************
    00077  */
    00078 struct mblock_free *ke_mem_init(void)
    00079 {
    00080     struct mblock_free *first;
    00081
    00082     // align first free descriptor to word boundary
    00083     #if CPU_WORD_SIZE == 4
    00084     first = (struct mblock_free*)CO_ALIGN4_HI((uint32_t)ke_mem_heap);
    00085     #elif CPU_WORD_SIZE == 2
    00086     first = (struct mblock_free*)CO_ALIGN2_HI((uint16_t)ke_mem_heap);
    00087     #else
    00088     #error No word size defined
    00089     #endif
    00090
    00091     // protect accesses to descriptors
    00092     GLOBAL_INT_DISABLE();
    00093
    00094     // initialize the first block
    00095     //  + compute the size from the last aligned word before heap_end
    00096     first->size = ((uint32_t)&ke_mem_heap[KE_HEAP_SIZE] & (~3)) - (uint32_t)first;
    00097     first->next = NULL;
    00098
    00099     // end of protection
    00100     GLOBAL_INT_RESTORE();
    00101
    00102     // save the pointer to the first free block
    00103     return first;
    00104 }
    00105
    00106 void *ke_malloc(uint32_t size)
    00107 {
    00108     struct mblock_free *node, *found;
    00109     struct mblock_used *alloc;
    00110     uint32_t totalsize;
    00111
    00112     #if KE_PROFILING
    00113     uint32_t totalfreesize = 0;
    00114     #endif //KE_PROFILING
    00115
    00116     // initialize the pointers
    00117     found = NULL;
    00118
    00119     // compute overall block size (including requested size PLUS descriptor size)
    00120     totalsize = CO_ALIGN4_HI(size) + sizeof(struct mblock_used);
    00121
    00122     // sanity check: the totalsize should be large enough to hold free block descriptor
    00123     ASSERT_ERR(totalsize >= sizeof(struct mblock_free));
    00124
    00125     node = ke_env.mblock_first;
    00126
    00127     // protect accesses to descriptors
    00128     GLOBAL_INT_DISABLE();
    00129
    00130     // go through free memory blocks list
    00131     while (node != NULL)
    00132     {
    00133         #if KE_PROFILING
    00134         totalfreesize += node->size;
    00135         #endif //KE_PROFILING
    00136
    00137         // check if there is enough room in this free block
    00138         if (node->size >= (totalsize + sizeof(struct mblock_free)))
    00139         {
    00140             // if a match was already found, check if this one is smaller
    00141             if ((found == NULL) || (found->size > node->size))
    00142             {
    00143                 found = node;
    00144             }
    00145         }
    00146         // move to next block
    00147         node = node->next;
    00148     }
    00149
    00150     // sanity check: allocation should always succeed
    00151     ASSERT_ERR(found != NULL);
    00152
    00153     #if KE_PROFILING
    00154     if(ke_env.max_heap_used <= KE_HEAP_SIZE - totalfreesize)
    00155         ke_env.max_heap_used = KE_HEAP_SIZE - totalfreesize;
    00156     #endif //KE_PROFILING
    00157
    00158     // found a free block that matches, subtract the allocation size from the
    00159     // free block size. If equal, the free block will be kept with 0 size... but
    00160     // moving it out of the linked list is too much work.
    00161     found->size -= totalsize;
    00162
    00163     // compute the pointer to the beginning of the free space
    00164     #if CPU_WORD_SIZE == 4
    00165     alloc = (struct mblock_used*) ((uint32_t)found + found->size);
    00166     #elif CPU_WORD_SIZE == 2
    00167     alloc = (struct mblock_used*) ((uint16_t)found + found->size);
    00168     #endif
    00169
    00170     // save the size of the allocated block (use low bit to indicate mem type)
    00171     alloc->size = totalsize;
    00172
    00173     // move to the user memory space
    00174     alloc++;
    00175
    00176     // end of protection (as early as possible)
    00177     GLOBAL_INT_RESTORE();
    00178
    00179     return (void*)alloc;
    00180 }
    00181
    00182
    00183 void ke_free(void* mem_ptr)
    00184 {
    00185     struct mblock_used *freed;
    00186     struct mblock_free *node, *prev_node, *next_node;
    00187     uint32_t size;
    00188
    00189     // point to the block descriptor (before user memory so decrement)
    00190     freed = ((struct mblock_used *)mem_ptr) - 1;
    00191
    00192     // point to the first node of the free elements linked list
    00193     size = freed->size;
    00194     node = ke_env.mblock_first;
    00195     prev_node = NULL;
    00196
    00197     // sanity checks
    00198     ASSERT_ERR(mem_ptr != NULL);
    00199     ASSERT_ERR((uint32_t)mem_ptr > (uint32_t)node);
    00200
    00201     // protect accesses to descriptors
    00202     GLOBAL_INT_DISABLE();
    00203
    00204     while (node != NULL)
    00205     {
    00206         // check if the freed block is right after the current block
    00207         if ((uint32_t)freed == ((uint32_t)node + node->size))
    00208         {
    00209             // append the freed block to the current one
    00210             node->size += size;
    00211
    00212             // check if this merge made the link between free blocks
    00213             if ((uint32_t)node->next == ((uint32_t)node + node->size))
    00214             {
    00215                 next_node = node->next;
    00216                 // add the size of the next node to the current node
    00217                 node->size += next_node->size;
    00218                 // update the next of the current node
    00219                 node->next = next_node->next;
    00220             }
    00221             goto free_end;
    00222         }
    00223         else if ((uint32_t)freed < (uint32_t)node)
    00224         {
    00225             // sanity check: can not happen before first node
    00226             ASSERT_ERR(prev_node != NULL);
    00227
    00228             // update the next pointer of the previous node
    00229             prev_node->next = (struct mblock_free*)freed;
    00230
    00231             // check if the released node is right before the free block
    00232             if (((uint32_t)freed + size) == (uint32_t)node)
    00233             {
    00234                 // merge the two nodes
    00235                 ((struct mblock_free*)freed)->next = node->next;
    00236                 ((struct mblock_free*)freed)->size = node->size + (uint32_t)node - (uint32_t)freed;
    00237             }
    00238             else
    00239             {
    00240                 // insert the new node
    00241                 ((struct mblock_free*)freed)->next = node;
    00242                 ((struct mblock_free*)freed)->size = size;
    00243             }
    00244             goto free_end;
    00245         }
    00246
    00247         // move to the next free block node
    00248         prev_node = node;
    00249         node = node->next;
    00250     }
    00251     // if reached here, freed block is after last free block and not contiguous
    00252     prev_node->next = (struct mblock_free*)freed;
    00253     ((struct mblock_free*)freed)->next = NULL;
    00254     ((struct mblock_free*)freed)->size = size;
    00255
    00256 free_end:
    00257     // end of protection
    00258     GLOBAL_INT_RESTORE();
    00259 }
    00260