2 * AcessOS Microkernel Version
13 #define HEAP_BASE 0xE0800000
14 #define HEAP_MAX 0xF0000000 // 120MiB, Plenty
15 #define HEAP_INIT_SIZE 0x8000 // 32 KiB
16 #define BLOCK_SIZE (sizeof(void*)) // 8 Machine Words
17 #define COMPACT_HEAP 0 // Use 4 byte header?
20 #define MAGIC_FOOT 0x2ACE5505
21 #define MAGIC_FREE 0xACE55000
22 #define MAGIC_USED 0x862B0505 // MAGIC_FOOT ^ MAGIC_FREE
26 void *Heap_Extend(int Bytes);
27 void *Heap_Merge(tHeapHead *Head);
28 void *malloc(size_t Bytes);
40 gHeapStart = (void*)MM_KHEAP_BASE;
41 gHeapEnd = (void*)MM_KHEAP_BASE;
42 Heap_Extend(HEAP_INIT_SIZE);
46 * \fn void *Heap_Extend(int Bytes)
47 * \brief Extend the size of the heap
49 void *Heap_Extend(int Bytes)
52 tHeapHead *head = gHeapEnd;
56 if( (Uint)gHeapEnd == MM_KHEAP_MAX )
60 if( (Uint)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) {
61 Bytes = MM_KHEAP_MAX - (Uint)gHeapEnd;
65 // Heap expands in pages
66 for(i=0;i<(Bytes+0xFFF)>>12;i++)
67 MM_Allocate( (Uint)gHeapEnd+(i<<12) );
73 head->Size = (Bytes+0xFFF)&~0xFFF;
74 head->Magic = MAGIC_FREE;
75 foot = (void*)( (Uint)gHeapEnd - sizeof(tHeapFoot) );
77 foot->Magic = MAGIC_FOOT;
79 //Log(" Heap_Extend: head = %p", head);
80 return Heap_Merge(head); // Merge with previous block
84 * \fn void *Heap_Merge(tHeapHead *Head)
85 * \brief Merges two ajacent heap blocks
87 void *Heap_Merge(tHeapHead *Head)
93 //Log("Heap_Merge: (Head=%p)", Head);
95 thisFoot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
96 if((Uint)thisFoot > (Uint)gHeapEnd) return NULL;
99 foot = (void*)( (Uint)Head - sizeof(tHeapFoot) );
100 if( ((Uint)foot < (Uint)gHeapEnd && (Uint)foot > HEAP_BASE)
101 && foot->Head->Magic == MAGIC_FREE) {
102 foot->Head->Size += Head->Size; // Increase size
103 thisFoot->Head = foot->Head; // Change backlink
104 Head->Magic = 0; // Clear old head
106 Head = foot->Head; // Save new head address
107 foot->Head = NULL; // Clear central footer
111 // Merge Right (Upwards)
112 head = (void*)( (Uint)Head + Head->Size );
113 if((Uint)head < (Uint)gHeapEnd && head->Magic == MAGIC_FREE)
115 Head->Size += head->Size;
116 foot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
117 foot->Head = Head; // Update Backlink
118 thisFoot->Head = NULL; // Clear old footer
120 head->Size = 0; // Clear old header
124 // Return new address
129 * \fn void *malloc(size_t Bytes)
130 * \brief Allocate memory from the heap
132 void *malloc(size_t Bytes)
134 tHeapHead *head, *newhead;
135 tHeapFoot *foot, *newfoot;
136 tHeapHead *best = NULL;
137 Uint bestSize = 0; // Speed hack
140 Bytes = (Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + BLOCK_SIZE-1) & ~(BLOCK_SIZE-1);
146 for( head = gHeapStart;
147 (Uint)head < (Uint)gHeapEnd;
148 head = (void*)((Uint)head + head->Size)
152 if( head->Size & (BLOCK_SIZE-1) ) {
154 Warning("Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
161 // Check if allocated
162 if(head->Magic == MAGIC_USED) continue;
164 if(head->Magic != MAGIC_FREE) {
166 Warning("Magic of heap address %p is invalid (0x%x)", head, head->Magic);
169 RELEASE(&glHeap); // Release spinlock
174 if(head->Size < Bytes) continue;
177 if(head->Size == Bytes) {
178 head->Magic = MAGIC_USED;
179 RELEASE(&glHeap); // Release spinlock
181 LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
189 bestSize = head->Size;
192 // or check if the block is the best size
193 if(bestSize > head->Size) {
195 bestSize = head->Size;
200 // If no block large enough is found, create one
203 best = Heap_Extend( Bytes );
206 RELEASE(&glHeap); // Release spinlock
210 if(best->Size == Bytes) {
211 RELEASE(&glHeap); // Release spinlock
213 LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
220 newhead = (void*)( (Uint)best + Bytes );
221 newfoot = (void*)( (Uint)best + Bytes - sizeof(tHeapFoot) );
222 foot = (void*)( (Uint)best + best->Size - sizeof(tHeapFoot) );
224 newfoot->Head = best; // Create new footer
225 newfoot->Magic = MAGIC_FOOT;
226 newhead->Size = best->Size - Bytes; // Create new header
227 newhead->Magic = MAGIC_FREE;
228 foot->Head = newhead; // Update backlink in old footer
229 best->Size = Bytes; // Update size in old header
230 best->Magic = MAGIC_USED; // Mark block as used
232 RELEASE(&glHeap); // Release spinlock
234 LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
240 * \fn void free(void *Ptr)
241 * \brief Free an allocated memory block
249 LOG("Ptr = %p", Ptr);
250 LOG("Returns to %p", __builtin_return_address(0));
254 if( (Uint)Ptr & (sizeof(Uint)-1) ) {
255 Warning("free - Passed a non-aligned address (%p)", Ptr);
260 if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
262 Warning("free - Passed a non-heap address (%p)\n", Ptr);
266 // Check memory block - Header
267 head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
268 if(head->Magic == MAGIC_FREE) {
269 Warning("free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
272 if(head->Magic != MAGIC_USED) {
273 Warning("free - Magic value is invalid (%p, 0x%x)\n", head, head->Magic);
277 // Check memory block - Footer
278 foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
279 if(foot->Head != head) {
280 Warning("free - Footer backlink is incorrect (%p, 0x%x)\n", head, foot->Head);
283 if(foot->Magic != MAGIC_FOOT) {
284 Warning("free - Footer magic is invalid (%p, %p = 0x%x)\n", head, &foot->Magic, foot->Magic);
292 head->Magic = MAGIC_FREE;
302 void *realloc(void *__ptr, size_t __size)
304 tHeapHead *head = (void*)( (Uint)__ptr-8 );
307 Uint newSize = (__size + sizeof(tHeapFoot)+sizeof(tHeapHead)+BLOCK_SIZE-1)&~(BLOCK_SIZE-1);
309 // Check for reallocating NULL
310 if(__ptr == NULL) return malloc(__size);
312 // Check if resize is needed
313 if(newSize <= head->Size) return __ptr;
315 // Check if next block is free
316 nextHead = (void*)( (Uint)head + head->Size );
318 // Extend into next block
319 if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
321 Uint size = nextHead->Size + head->Size;
322 foot = (void*)( (Uint)nextHead + nextHead->Size - sizeof(tHeapFoot) );
324 if(size == newSize) {
325 head->Size = newSize;
331 // Create a new heap block
332 nextHead = (void*)( (Uint)head + newSize );
333 nextHead->Size = size - newSize;
334 nextHead->Magic = MAGIC_FREE;
335 foot->Head = nextHead; // Edit 2nd footer
336 head->Size = newSize; // Edit first header
338 foot = (void*)( (Uint)head + newSize - sizeof(tHeapFoot) );
340 foot->Magic = MAGIC_FOOT;
345 foot = (void*)( (Uint)head - sizeof(tHeapFoot) );
346 nextHead = foot->Head;
347 if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
349 Uint size = nextHead->Size + head->Size;
354 // Set 1st (new/lower) header
355 nextHead->Magic = MAGIC_USED;
356 nextHead->Size = newSize;
357 // Get 2nd (old) footer
358 foot = (void*)( (Uint)nextHead + newSize );
359 foot->Head = nextHead;
360 // Save old data size
361 oldDataSize = head->Size - sizeof(tHeapFoot) - sizeof(tHeapHead);
365 memcpy(nextHead->Data, __ptr, oldDataSize);
373 * \fn void *calloc(size_t num, size_t size)
374 * \brief Allocate and Zero a buffer in memory
375 * \param num Number of elements
376 * \param size Size of each element
378 void *calloc(size_t num, size_t size)
380 void *ret = malloc(num*size);
381 if(ret == NULL) return NULL;
383 memset( ret, 0, num*size );
389 * \fn int IsHeap(void *Ptr)
390 * \brief Checks if an address is a heap address
392 int IsHeap(void *Ptr)
395 if((Uint)Ptr < (Uint)gHeapStart) return 0;
396 if((Uint)Ptr > (Uint)gHeapEnd) return 0;
398 head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
399 if(head->Magic != MAGIC_USED && head->Magic != MAGIC_FREE)
412 while( (Uint)head < (Uint)gHeapEnd )
414 foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
415 Log("%p (0x%x): 0x%08lx 0x%lx", head, MM_GetPhysAddr((Uint)head), head->Size, head->Magic);
416 Log("%p 0x%lx", foot->Head, foot->Magic);
419 // Sanity Check Header
420 if(head->Size == 0) {
421 Log("HALTED - Size is zero");
424 if(head->Size & (BLOCK_SIZE-1)) {
425 Log("HALTED - Size is malaligned");
428 if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
429 Log("HALTED - Head Magic is Bad");
434 if(foot->Magic != MAGIC_FOOT) {
435 Log("HALTED - Foot Magic is Bad");
438 if(head != foot->Head) {
439 Log("HALTED - Footer backlink is invalid");
443 // All OK? Go to next
444 head = foot->NextHead;