* AcessOS Microkernel Version
* heap.c
*/
-#include <common.h>
+#include <acess.h>
#include <mm_virt.h>
#include <heap.h>
#define WARNINGS 1
+#define DEBUG_TRACE 0
// === CONSTANTS ===
-#define HEAP_BASE 0xE0800000
-#define HEAP_MAX 0xF0000000 // 120MiB, Plenty
#define HEAP_INIT_SIZE 0x8000 // 32 KiB
#define BLOCK_SIZE (sizeof(void*)) // 8 Machine Words
#define COMPACT_HEAP 0 // Use 4 byte header?
void Heap_Dump();
// === GLOBALS ===
- int giHeapSpinlock;
+tSpinlock glHeap;
void *gHeapStart;
void *gHeapEnd;
tHeapFoot *foot;
// Bounds Check
- if( (Uint)gHeapEnd == MM_KHEAP_MAX )
+ if( (tVAddr)gHeapEnd == MM_KHEAP_MAX )
return NULL;
// Bounds Check
- if( (Uint)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) {
- Bytes = MM_KHEAP_MAX - (Uint)gHeapEnd;
+ if( (tVAddr)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) {
+ Bytes = MM_KHEAP_MAX - (tVAddr)gHeapEnd;
return NULL;
}
// Heap expands in pages
for(i=0;i<(Bytes+0xFFF)>>12;i++)
- MM_Allocate( (Uint)gHeapEnd+(i<<12) );
+ MM_Allocate( (tVAddr)gHeapEnd+(i<<12) );
// Increas heap end
gHeapEnd += i << 12;
foot->Head = head;
foot->Magic = MAGIC_FOOT;
- //Log(" Heap_Extend: head = %p", head);
return Heap_Merge(head); // Merge with previous block
}
// Merge Left (Down)
foot = (void*)( (Uint)Head - sizeof(tHeapFoot) );
- if( ((Uint)foot < (Uint)gHeapEnd && (Uint)foot > HEAP_BASE)
+ if( ((Uint)foot < (Uint)gHeapEnd && (Uint)foot > (Uint)gHeapStart)
&& foot->Head->Magic == MAGIC_FREE) {
foot->Head->Size += Head->Size; // Increase size
thisFoot->Head = foot->Head; // Change backlink
Bytes = (Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + BLOCK_SIZE-1) & ~(BLOCK_SIZE-1);
// Lock Heap
- LOCK(&giHeapSpinlock);
+ LOCK(&glHeap);
// Traverse Heap
for( head = gHeapStart;
// Alignment Check
if( head->Size & (BLOCK_SIZE-1) ) {
#if WARNINGS
- Warning("Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
+ Log_Warning("Heap", "Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
Heap_Dump();
#endif
+ RELEASE(&glHeap);
return NULL;
}
// Error check
if(head->Magic != MAGIC_FREE) {
#if WARNINGS
- Warning("Magic of heap address %p is invalid (0x%x)", head, head->Magic);
+ Log_Warning("Heap", "Magic of heap address %p is invalid (0x%x)", head, head->Magic);
Heap_Dump();
#endif
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
return NULL;
}
// Perfect fit
if(head->Size == Bytes) {
head->Magic = MAGIC_USED;
- RELEASE(&giHeapSpinlock); // Release spinlock
- return best->Data;
+ RELEASE(&glHeap); // Release spinlock
+ #if DEBUG_TRACE
+ Log("[Heap ] Malloc'd %p (%i bytes), returning to %p", head->Data, head->Size, __builtin_return_address(0));
+ #endif
+ return head->Data;
}
// Break out of loop
best = Heap_Extend( Bytes );
// Check for errors
if(!best) {
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
return NULL;
}
// Check size
if(best->Size == Bytes) {
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
+ #if DEBUG_TRACE
+ Log("[Heap ] Malloc'd %p (%i bytes), returning to %p", best->Data, best->Size, __builtin_return_address(0));
+ #endif
return best->Data;
}
}
best->Size = Bytes; // Update size in old header
best->Magic = MAGIC_USED; // Mark block as used
- RELEASE(&giHeapSpinlock); // Release spinlock
+ RELEASE(&glHeap); // Release spinlock
+ #if DEBUG_TRACE
+ Log("[Heap ] Malloc'd %p (%i bytes), returning to %p", best->Data, best->Size, __builtin_return_address(0));
+ #endif
return best->Data;
}
tHeapHead *head;
tHeapFoot *foot;
- LOG("Ptr = %p", Ptr);
- LOG("Returns to %p", __builtin_return_address(0));
+ #if DEBUG_TRACE
+ Log_Log("Heap", "free: Ptr = %p", Ptr);
+ Log_Log("Heap", "free: Returns to %p", __builtin_return_address(0));
+ #endif
// Alignment Check
if( (Uint)Ptr & (sizeof(Uint)-1) ) {
- Warning("free - Passed a non-aligned address (%p)\n", Ptr);
+ Log_Warning("Heap", "free - Passed a non-aligned address (%p)", Ptr);
return;
}
// Sanity check
if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
{
- Warning("free - Passed a non-heap address (%p)\n", Ptr);
+ Log_Warning("Heap", "free - Passed a non-heap address (%p < %p < %p)\n",
+ gHeapStart, Ptr, gHeapEnd);
return;
}
// Check memory block - Header
head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
if(head->Magic == MAGIC_FREE) {
- Warning("free - Passed a freed block (%p)\n", head);
+ Log_Warning("Heap", "free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
return;
}
if(head->Magic != MAGIC_USED) {
- Warning("free - Magic value is invalid (%p, 0x%x)\n", head, head->Magic);
+ Log_Warning("Heap", "free - Magic value is invalid (%p, 0x%x)\n", head, head->Magic);
return;
}
// Check memory block - Footer
foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
if(foot->Head != head) {
- Warning("free - Footer backlink is incorrect (%p, 0x%x)\n", head, foot->Head);
+ Log_Warning("Heap", "free - Footer backlink is incorrect (%p, 0x%x)\n", head, foot->Head);
return;
}
if(foot->Magic != MAGIC_FOOT) {
- Warning("free - Footer magic is invalid (%p, 0x%x)\n", head, foot->Magic);
+ Log_Warning("Heap", "free - Footer magic is invalid (%p, %p = 0x%x)\n", head, &foot->Magic, foot->Magic);
return;
}
// Lock
- LOCK( &giHeapSpinlock );
+ LOCK( &glHeap );
// Mark as free
head->Magic = MAGIC_FREE;
Heap_Merge( head );
// Release
- RELEASE( &giHeapSpinlock );
+ RELEASE( &glHeap );
}
/**
return NULL;
}
+/**
+ * \fn void *calloc(size_t num, size_t size)
+ * \brief Allocate and Zero a buffer in memory
+ * \param num Number of elements
+ * \param size Size of each element
+ */
+void *calloc(size_t num, size_t size)
+{
+ void *ret = malloc(num*size);
+ if(ret == NULL) return NULL;
+
+ memset( ret, 0, num*size );
+
+ return ret;
+}
+
+/**
+ * \fn int IsHeap(void *Ptr)
+ * \brief Checks if an address is a heap pointer
+ */
+int IsHeap(void *Ptr)
+{
+ tHeapHead *head;
+ if((Uint)Ptr < (Uint)gHeapStart) return 0;
+ if((Uint)Ptr > (Uint)gHeapEnd) return 0;
+ if((Uint)Ptr & (sizeof(Uint)-1)) return 0;
+
+ head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
+ if(head->Magic != MAGIC_USED && head->Magic != MAGIC_FREE)
+ return 0;
+
+ return 1;
+}
+
#if WARNINGS
void Heap_Dump()
{
while( (Uint)head < (Uint)gHeapEnd )
{
foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
- Log("%p (0x%x): 0x%08lx 0x%lx", head, MM_GetPhysAddr((Uint)head), head->Size, head->Magic);
- Log("%p 0x%lx", foot->Head, foot->Magic);
- Log("");
+ Log_Log("Heap", "%p (0x%x): 0x%08lx 0x%lx", head, MM_GetPhysAddr((Uint)head), head->Size, head->Magic);
+ Log_Log("Heap", "%p 0x%lx", foot->Head, foot->Magic);
+ Log_Log("Heap", "");
// Sanity Check Header
if(head->Size == 0) {
- Log("HALTED - Size is zero");
+ Log_Warning("Heap", "HALTED - Size is zero");
break;
}
if(head->Size & (BLOCK_SIZE-1)) {
- Log("HALTED - Size is malaligned");
+ Log_Warning("Heap", "HALTED - Size is malaligned");
break;
}
if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
- Log("HALTED - Head Magic is Bad");
+ Log_Warning("Heap", "HALTED - Head Magic is Bad");
break;
}
// Check footer
if(foot->Magic != MAGIC_FOOT) {
- Log("HALTED - Foot Magic is Bad");
+ Log_Warning("Heap", "HALTED - Foot Magic is Bad");
break;
}
if(head != foot->Head) {
- Log("HALTED - Footer backlink is invalid");
+ Log_Warning("Heap", "HALTED - Footer backlink is invalid");
break;
}
}
}
#endif
+
+// === EXPORTS ===
+EXPORT(malloc);
+EXPORT(realloc);
+EXPORT(free);