POK
|
00001 /* 00002 * POK header 00003 * 00004 * The following file is a part of the POK project. Any modification should 00005 * made according to the POK licence. You CANNOT use this file or a part of 00006 * this file is this part of a file for your own project 00007 * 00008 * For more information on the POK licence, please see our LICENCE FILE 00009 * 00010 * Please follow the coding guidelines described in doc/CODING_GUIDELINES 00011 * 00012 * Copyright (c) 2007-2009 POK team 00013 * 00014 * Created by julien on Thu Jul 30 15:49:30 2009 00015 */ 00016 00017 #include <core/dependencies.h> 00018 #include <core/allocator.h> 00019 00020 /* 00021 * This is the allocator of POK. It remains in partition. You can configure it 00022 * with POK_CONFIG_ALLOCATOR_MEMORY_SIZE (total amount of memory that can be allocated 00023 * and with POK_CONFIG_ALLOCATOR_NB_SPACES (total amount of memory spaces that can be 00024 * allocated (number of successive calls to malloc() or calloc() for example. 00025 */ 00026 00027 #ifdef POK_NEEDS_ALLOCATOR 00028 00029 #ifndef POK_CONFIG_ALLOCATOR_MEMORY_SIZE 00030 #define POK_CONFIG_ALLOCATOR_MEMORY_SIZE 16384 00031 #endif 00032 00033 #ifndef POK_CONFIG_ALLOCATOR_NB_SPACES 00034 #define POK_CONFIG_ALLOCATOR_NB_SPACES 100 00035 #endif 00036 00037 #define POK_ALLOCATOR_CHECK_INIT \ 00038 if (pok_allocator_initialized == 0)\ 00039 { \ 00040 uint32_t toto; \ 00041 for (toto = 0 ; toto < POK_CONFIG_ALLOCATOR_NB_SPACES ; toto++) \ 00042 { \ 00043 pok_allocator_spaces[toto].start = 0; \ 00044 pok_allocator_spaces[toto].size = 0; \ 00045 pok_allocator_spaces[toto].allocated = 0; \ 00046 } \ 00047 pok_allocator_used_spaces = 1; \ 00048 pok_allocator_spaces[0].start = 0; /* Initialize the first space */ \ 00049 pok_allocator_spaces[0].allocated = 0; \ 00050 pok_allocator_spaces[0].size = POK_CONFIG_ALLOCATOR_MEMORY_SIZE;\ 00051 pok_allocator_initialized = 1; \ 00052 } 00053 00054 /* POK_ALLOCATOR_CHECK_INIT is a macro that performs initialization functions 00055 * for memory allocator. It is called each time alloc or free functions are called 00056 * but initialized the memory allocator only one time. 00057 */ 00058 00059 00060 typedef struct 00061 { 00062 size_t start; 00063 size_t size; 00064 bool_t allocated; 00065 } pok_allocator_space_t; 00066 00067 00068 uint8_t pok_allocator_memspace[POK_CONFIG_ALLOCATOR_MEMORY_SIZE]; 00069 pok_allocator_space_t pok_allocator_spaces[POK_CONFIG_ALLOCATOR_NB_SPACES]; 00070 uint32_t pok_allocator_used_spaces = 0; 00071 bool_t pok_allocator_initialized = 0; 00072 00073 #ifdef POK_NEEDS_DEBUG 00074 void pok_allocator_print_spaces () 00075 { 00076 uint32_t space; 00077 printf ("[LIBPOK] [ALLOCATOR] Used spaces = %d\n", pok_allocator_used_spaces); 00078 for (space = 0 ; space < pok_allocator_used_spaces ; space++) 00079 { 00080 printf ("[LIBPOK] [ALLOCATOR] Space %d start=%d size=%d allocated=%d\n", space, pok_allocator_spaces[space].start, pok_allocator_spaces[space].size, pok_allocator_spaces[space].allocated); 00081 } 00082 } 00083 #endif 00084 00085 void* pok_allocator_allocate (size_t needed_size) 00086 { 00087 POK_ALLOCATOR_CHECK_INIT 00088 uint32_t space; 00089 uint32_t new_space; 00090 00091 if (pok_allocator_used_spaces >= (POK_CONFIG_ALLOCATOR_NB_SPACES - 1)) 00092 { 00093 #ifdef POK_NEEDS_DEBUG 00094 printf ("[LIBPOK] [ALLOCATOR] Not enough space\n"); 00095 #endif 00096 return NULL; 00097 } 00098 00099 #ifdef POK_NEEDS_DEBUG 00100 printf("Try to take a new memory chunk, required space=%d\n", needed_size); 00101 #endif 00102 00103 for (space = 0 ; space < pok_allocator_used_spaces ; space++) 00104 { 00105 #ifdef POK_NEEDS_DEBUG 00106 printf ("[LIBPOK] [ALLOCATOR] Look space %d, size %d, allocated=%d\n", space, pok_allocator_spaces[space].size, pok_allocator_spaces[space].allocated); 00107 #endif 00108 if ((pok_allocator_spaces[space].allocated == 0) && (pok_allocator_spaces[space].size >= needed_size)) 00109 { 00110 if (pok_allocator_spaces[space].size == needed_size) 00111 { 00112 /* 00113 * The space corresponds exactly to the requested memory space 00114 */ 00115 pok_allocator_spaces[space].allocated = 1; 00116 00117 #ifdef POK_NEEDS_DEBUG 00118 printf ("[LIBPOK] [ALLOCATOR] Allocate directly space %d\n", space); 00119 pok_allocator_print_spaces (); 00120 #endif 00121 return (&pok_allocator_memspace[pok_allocator_spaces[space].start]); 00122 } 00123 else 00124 { 00125 /* 00126 * We need to split the block in two new blocks ! 00127 */ 00128 new_space = pok_allocator_used_spaces; 00129 pok_allocator_used_spaces = pok_allocator_used_spaces + 1; 00130 00131 pok_allocator_spaces[space].allocated = 1; 00132 pok_allocator_spaces[new_space].allocated = 0; 00133 00134 pok_allocator_spaces[new_space].size = pok_allocator_spaces[space].size - needed_size; 00135 pok_allocator_spaces[space].size = needed_size; 00136 00137 pok_allocator_spaces[new_space].start = pok_allocator_spaces[space].start + needed_size; 00138 00139 #ifdef POK_NEEDS_DEBUG 00140 printf("[LIBPOK] [ALLOCATOR] Allocate space %d, CREATE NEW SPACE %d (size=%d)\n", space, new_space, pok_allocator_spaces[new_space].size); 00141 pok_allocator_print_spaces (); 00142 #endif 00143 00144 return (&pok_allocator_memspace[pok_allocator_spaces[space].start]); 00145 } 00146 } 00147 } 00148 00149 #ifdef POK_NEEDS_DEBUG 00150 printf ("[LIBPOK] [ALLOCATOR] Didn't find any space for that amount of memory (%d)\n", needed_size); 00151 #endif 00152 return NULL; 00153 } 00154 00155 /* 00156 * Delete a space 00157 */ 00158 void pok_allocator_delete_space (uint32_t space) 00159 { 00160 uint32_t tmp; 00161 00162 #ifdef POK_NEEDS_DEBUG 00163 printf("[LIBPOK] [ALLOCATOR] Delete space %d\n", space); 00164 #endif 00165 00166 for (tmp = space ; tmp < POK_CONFIG_ALLOCATOR_NB_SPACES ; tmp++) 00167 { 00168 pok_allocator_spaces[tmp].allocated = pok_allocator_spaces[tmp+1].allocated; 00169 pok_allocator_spaces[tmp].size = pok_allocator_spaces[tmp+1].size; 00170 pok_allocator_spaces[tmp].start = pok_allocator_spaces[tmp+1].start; 00171 } 00172 00173 pok_allocator_used_spaces = pok_allocator_used_spaces - 1; 00174 } 00175 00176 void pok_allocator_merge_space (uint32_t space) 00177 { 00178 uint32_t space2; 00179 00180 if (pok_allocator_used_spaces == 1) 00181 { 00182 return; 00183 } 00184 00185 for (space2 = 0 ; space2 < pok_allocator_used_spaces ; space2++) 00186 { 00187 if ((space2 == space) || (pok_allocator_spaces[space2].allocated == 1)) 00188 { 00189 continue; 00190 } 00191 00192 /* 00193 * In that case, space is a the end of space2. We can merge space in space2 00194 */ 00195 if (pok_allocator_spaces[space].start == (pok_allocator_spaces[space2].start + pok_allocator_spaces[space2].size)) 00196 { 00197 #ifdef POK_NEEDS_DEBUG 00198 // printf("[LIBPOK] [ALLOCATOR] Merge space %d, with %d\n", space, space2); 00199 #endif 00200 pok_allocator_spaces[space2].size = pok_allocator_spaces[space2].size + pok_allocator_spaces[space].size; 00201 pok_allocator_delete_space (space); 00202 pok_allocator_merge_space (space2); 00203 return; 00204 } 00205 00206 /* 00207 * In that case, space2 is located at the end of space. We can merge space2 in space 00208 */ 00209 if (pok_allocator_spaces[space2].start == (pok_allocator_spaces[space].start + pok_allocator_spaces[space].size)) 00210 { 00211 #ifdef POK_NEEDS_DEBUG 00212 // printf("[LIBPOK] [ALLOCATOR] Merge space %d, with %d\n", space, space2); 00213 #endif 00214 pok_allocator_spaces[space].size = pok_allocator_spaces[space].size + pok_allocator_spaces[space2].size; 00215 pok_allocator_delete_space (space2); 00216 pok_allocator_merge_space (space2); 00217 return; 00218 } 00219 } 00220 } 00221 00222 00223 void pok_allocator_free (void* ptr) 00224 { 00225 POK_ALLOCATOR_CHECK_INIT 00226 00227 uint32_t space; 00228 00229 for (space = 0 ; space < pok_allocator_used_spaces ; space++) 00230 { 00231 if (ptr == &pok_allocator_memspace[pok_allocator_spaces[space].start]) 00232 { 00233 /* Here, we find the space to free */ 00234 pok_allocator_spaces[space].allocated = 0; 00235 pok_allocator_merge_space (space); 00236 #ifdef POK_NEEDS_DEBUG 00237 pok_allocator_print_spaces (); 00238 #endif 00239 return; 00240 } 00241 } 00242 00243 #ifdef POK_NEEDS_DEBUG 00244 printf("[LIBPOK] [ALLOCATOR] free() didn't find the space to free\n"); 00245 pok_allocator_print_spaces (); 00246 #endif 00247 return; 00248 } 00249 00250 #endif 00251