heap.c
Go to the documentation of this file.00001
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #include "heap.h"
00070 #include <string.h>
00071 #include <cfg/macros.h>
00072 #include <cfg/debug.h>
00073
00074
00075 typedef struct _MemChunk
00076 {
00077 struct _MemChunk *next;
00078 size_t size;
00079 } MemChunk;
00080
00081 STATIC_ASSERT(IS_POW2(sizeof(MemChunk)));
00082
00083 #define FREE_FILL_CODE 0xDEAD
00084 #define ALLOC_FILL_CODE 0xBEEF
00085
00086 void heap_init(struct Heap* h, void* memory, size_t size)
00087 {
00088 #ifdef _DEBUG
00089 memset(memory, FREE_FILL_CODE, size);
00090 #endif
00091
00092
00093 h->FreeList = (MemChunk *)memory;
00094 h->FreeList->next = NULL;
00095 h->FreeList->size = size;
00096 }
00097
00098
00099 void *heap_allocmem(struct Heap* h, size_t size)
00100 {
00101 MemChunk *chunk, *prev;
00102
00103
00104 size = ROUND2(size, sizeof(MemChunk));
00105
00106
00107 if (!size)
00108 size = sizeof(MemChunk);
00109
00110
00111
00112
00113 for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
00114 chunk;
00115 prev = chunk, chunk = chunk->next)
00116 {
00117 if (chunk->size >= size)
00118 {
00119 if (chunk->size == size)
00120 {
00121
00122 prev->next = chunk->next;
00123 #ifdef _DEBUG
00124 memset(chunk, ALLOC_FILL_CODE, size);
00125 #endif
00126 return (void *)chunk;
00127 }
00128 else
00129 {
00130
00131 chunk->size -= size;
00132 #ifdef _DEBUG
00133 memset((uint8_t *)chunk + chunk->size, ALLOC_FILL_CODE, size);
00134 #endif
00135 return (void *)((uint8_t *)chunk + chunk->size);
00136 }
00137 }
00138 }
00139
00140 return NULL;
00141 }
00142
00143
00144 void heap_freemem(struct Heap* h, void *mem, size_t size)
00145 {
00146 MemChunk *prev;
00147
00148 ASSERT(mem);
00149
00150 #ifdef _DEBUG
00151 memset(mem, FREE_FILL_CODE, size);
00152 #endif
00153
00154
00155 size = ROUND2(size, sizeof(MemChunk));
00156
00157
00158 if (!size)
00159 size = sizeof(MemChunk);
00160
00161
00162 ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList);
00163 if (((uint8_t *)mem) < ((uint8_t *)h->FreeList))
00164 {
00165
00166 prev = (MemChunk *)mem;
00167 prev->next = h->FreeList;
00168 prev->size = size;
00169 h->FreeList = prev;
00170 }
00171 else
00172 {
00173
00174
00175
00176
00177 prev = h->FreeList;
00178 while (prev->next < (MemChunk *)mem && prev->next)
00179 prev = prev->next;
00180
00181
00182 ASSERT((uint8_t*)mem >= (uint8_t*)prev + prev->size);
00183
00184
00185 if (((uint8_t *)prev) + prev->size == ((uint8_t *)mem))
00186 {
00187
00188 prev->size += size;
00189 }
00190 else
00191 {
00192 MemChunk *curr = (MemChunk*)mem;
00193
00194
00195
00196
00197
00198 curr->next = prev->next;
00199 curr->size = size;
00200 prev->next = curr;
00201
00202
00203 prev = curr;
00204 }
00205 }
00206
00207
00208 if (((uint8_t *)prev) + prev->size == ((uint8_t *)prev->next))
00209 {
00210 prev->size += prev->next->size;
00211 prev->next = prev->next->next;
00212
00213
00214 ASSERT((uint8_t*)prev + prev->size != (uint8_t*)prev->next);
00215 }
00216 }
00217
00218 #if CONFIG_HEAP_MALLOC
00219
00220 void *heap_malloc(struct Heap* h, size_t size)
00221 {
00222 size_t *mem;
00223
00224 size += sizeof(size_t);
00225 if ((mem = (size_t*)heap_allocmem(h, size)))
00226 *mem++ = size;
00227
00228 return mem;
00229 }
00230
00231 void *heap_calloc(struct Heap* h, size_t size)
00232 {
00233 void *mem;
00234
00235 if ((mem = heap_malloc(h, size)))
00236 memset(mem, 0, size);
00237
00238 return mem;
00239 }
00240
00254 void heap_free(struct Heap *h, void *mem)
00255 {
00256 size_t *_mem = (size_t *)mem;
00257
00258 if (_mem)
00259 {
00260 --_mem;
00261 heap_freemem(h, _mem, *_mem);
00262 }
00263 }
00264
00265 #endif