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