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