#define WARNINGS 1
#define DEBUG_TRACE 0
+#define VERBOSE_DUMP 0
// === CONSTANTS ===
#define HEAP_INIT_SIZE 0x8000 // 32 KiB
void Heap_Install(void);
void *Heap_Extend(int Bytes);
void *Heap_Merge(tHeapHead *Head);
-void *Heap_Allocate(const char *File, int Line, size_t Bytes);
-void *Heap_AllocateZero(const char *File, int Line, size_t Bytes);
-void *Heap_Reallocate(const char *File, int Line, void *Ptr, size_t Bytes);
-void Heap_Deallocate(void *Ptr);
+//void *Heap_Allocate(const char *File, int Line, size_t Bytes);
+//void *Heap_AllocateZero(const char *File, int Line, size_t Bytes);
+//void *Heap_Reallocate(const char *File, int Line, void *Ptr, size_t Bytes);
+//void Heap_Deallocate(void *Ptr);
void Heap_Dump(void);
void Heap_Stats(void);
// === GLOBALS ===
-tSpinlock glHeap;
+tMutex glHeap;
void *gHeapStart;
void *gHeapEnd;
if( (tVAddr)gHeapEnd == MM_KHEAP_MAX )
return NULL;
+ if( Bytes == 0 ) {
+ Log_Warning("Heap", "Heap_Extend called with Bytes=%i", Bytes);
+ return NULL;
+ }
+
// Bounds Check
if( (tVAddr)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) {
Bytes = MM_KHEAP_MAX - (tVAddr)gHeapEnd;
}
// Heap expands in pages
- for(i=0;i<(Bytes+0xFFF)>>12;i++)
- MM_Allocate( (tVAddr)gHeapEnd+(i<<12) );
+ for( i = 0; i < (Bytes+0xFFF) >> 12; i ++ )
+ {
+ if( !MM_Allocate( (tVAddr)gHeapEnd+(i<<12) ) )
+ {
+ Warning("OOM - Heap_Extend");
+ return NULL;
+ }
+ }
// Increas heap end
- gHeapEnd += i << 12;
+ gHeapEnd = (Uint8*)gHeapEnd + (i << 12);
// Create Block
head->Size = (Bytes+0xFFF)&~0xFFF;
* \param Line Source line
* \param Bytes Size of region to allocate
*/
-void *Heap_Allocate(const char *File, int Line, size_t Bytes)
+void *Heap_Allocate(const char *File, int Line, size_t __Bytes)
{
tHeapHead *head, *newhead;
tHeapFoot *foot, *newfoot;
tHeapHead *best = NULL;
Uint bestSize = 0; // Speed hack
+ size_t Bytes;
+
+ if( __Bytes == 0 ) {
+ //return NULL; // TODO: Return a known un-mapped range.
+ return INVLPTR;
+ }
// Get required size
#if POW2_SIZES
- Bytes = Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot);
- Bytes = 1UUL << LOG2(Bytes);
+ Bytes = __Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot);
+ Bytes = 1UUL << LOG2(__Bytes);
#else
- Bytes = (Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + MIN_SIZE-1) & ~(MIN_SIZE-1);
+ Bytes = (__Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + MIN_SIZE-1) & ~(MIN_SIZE-1);
#endif
// Lock Heap
- LOCK(&glHeap);
+ Mutex_Acquire(&glHeap);
// Traverse Heap
for( head = gHeapStart;
#else
if( head->Size & (MIN_SIZE-1) ) {
#endif
- RELEASE(&glHeap); // Release spinlock
+ Mutex_Release(&glHeap); // Release spinlock
#if WARNINGS
Log_Warning("Heap", "Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
Heap_Dump();
if(head->Magic == MAGIC_USED) continue;
// Error check
if(head->Magic != MAGIC_FREE) {
- RELEASE(&glHeap); // Release spinlock
+ Mutex_Release(&glHeap); // Release spinlock
#if WARNINGS
Log_Warning("Heap", "Magic of heap address %p is invalid (0x%x)", head, head->Magic);
Heap_Dump();
head->Magic = MAGIC_USED;
head->File = File;
head->Line = Line;
- RELEASE(&glHeap); // Release spinlock
+ Mutex_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
best = Heap_Extend( Bytes );
// Check for errors
if(!best) {
- RELEASE(&glHeap); // Release spinlock
+ Mutex_Release(&glHeap); // Release spinlock
return NULL;
}
// Check size
best->Magic = MAGIC_USED; // Mark block as used
best->File = File;
best->Line = Line;
- RELEASE(&glHeap); // Release spinlock
+ Mutex_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
newhead->Magic = MAGIC_FREE;
foot->Head = newhead; // Update backlink in old footer
best->Size = Bytes; // Update size in old header
+ best->ValidSize = __Bytes;
best->Magic = MAGIC_USED; // Mark block as used
best->File = File;
best->Line = Line;
- RELEASE(&glHeap); // Release spinlock
+ Mutex_Release(&glHeap); // Release spinlock
#if DEBUG_TRACE
Log_Debug("Heap", "newhead(%p)->Size = 0x%x", newhead, newhead->Size);
Log_Debug("Heap", "Malloc'd %p (0x%x bytes), returning to %s:%i",
Log_Log("Heap", "free: Returns to %p", __builtin_return_address(0));
#endif
+ // INVLPTR is returned from Heap_Allocate when the allocation
+ // size is zero.
+ if( Ptr == INVLPTR ) return;
+
// Alignment Check
if( (Uint)Ptr & (sizeof(Uint)-1) ) {
Log_Warning("Heap", "free - Passed a non-aligned address (%p)", Ptr);
}
if(head->Magic != MAGIC_USED) {
Log_Warning("Heap", "free - Magic value is invalid (%p, 0x%x)", head, head->Magic);
- Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
+ Log_Notice("Heap", "Allocated by %s:%i", head->File, head->Line);
return;
}
foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
if(foot->Head != head) {
Log_Warning("Heap", "free - Footer backlink is incorrect (%p, 0x%x)", head, foot->Head);
- Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
+ Log_Notice("Heap", "Allocated by %s:%i", head->File, head->Line);
return;
}
if(foot->Magic != MAGIC_FOOT) {
Log_Warning("Heap", "free - Footer magic is invalid (%p, %p = 0x%x)", head, &foot->Magic, foot->Magic);
- Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
+ Log_Notice("Heap", "Allocated by %s:%i", head->File, head->Line);
return;
}
// Lock
- LOCK( &glHeap );
+ Mutex_Acquire( &glHeap );
// Mark as free
head->Magic = MAGIC_FREE;
+ //head->File = NULL;
+ //head->Line = 0;
+ head->ValidSize = 0;
// Merge blocks
Heap_Merge( head );
// Release
- RELEASE( &glHeap );
+ Mutex_Release( &glHeap );
}
/**
+ * \brief Increase/Decrease the size of an allocation
+ * \param File Calling File
+ * \param Line Calling Line
+ * \param __ptr Old memory
+ * \param __size New Size
*/
void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size)
{
- tHeapHead *head = (void*)( (Uint)__ptr-8 );
+ tHeapHead *head = (void*)( (Uint)__ptr-sizeof(tHeapHead) );
tHeapHead *nextHead;
tHeapFoot *foot;
Uint newSize = (__size + sizeof(tHeapFoot)+sizeof(tHeapHead)+MIN_SIZE-1)&~(MIN_SIZE-1);
// Exact Fit
if(size == newSize) {
head->Size = newSize;
+ head->ValidSize = __size;
head->File = File;
head->Line = Line;
foot->Head = head;
head->Size = newSize; // Edit first header
head->File = File;
head->Line = Line;
+ head->ValidSize = __size;
// Create new footer
foot = (void*)( (Uint)head + newSize - sizeof(tHeapFoot) );
foot->Head = head;
nextHead->Size = newSize;
nextHead->File = File;
nextHead->Line = Line;
+ nextHead->ValidSize = __size;
// Get 2nd (old) footer
foot = (void*)( (Uint)nextHead + newSize );
foot->Head = nextHead;
nextHead -= 1;
nextHead->File = File;
nextHead->Line = Line;
+ nextHead->ValidSize = __size;
memcpy(
nextHead->Data,
}
/**
- * \fn void *Heap_AllocateZero(const char *File, int Line, size_t size)
+ * \fn void *Heap_AllocateZero(const char *File, int Line, size_t Bytes)
* \brief Allocate and Zero a buffer in memory
* \param File Allocating file
* \param Line Line of allocation
- * \param size Size of the allocation
+ * \param Bytes Size of the allocation
*/
-void *Heap_AllocateZero(const char *File, int Line, size_t size)
+void *Heap_AllocateZero(const char *File, int Line, size_t Bytes)
{
- void *ret = Heap_Allocate(File, Line, size);
+ void *ret = Heap_Allocate(File, Line, Bytes);
if(ret == NULL) return NULL;
- memset( ret, 0, size );
+ memset( ret, 0, Bytes );
return ret;
}
return 1;
}
+/**
+ */
+void Heap_Validate(void)
+{
+ Heap_Dump();
+}
+
#if WARNINGS
void Heap_Dump(void)
{
tHeapHead *head, *badHead;
- tHeapFoot *foot;
+ tHeapFoot *foot = NULL;
head = gHeapStart;
while( (Uint)head < (Uint)gHeapEnd )
{
foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
- Log_Log("Heap", "%p (0x%llx): 0x%08lx %4C",
- head, MM_GetPhysAddr((Uint)head), head->Size, &head->Magic);
+ #if VERBOSE_DUMP
+ Log_Log("Heap", "%p (0x%llx): 0x%08lx (%i) %4C",
+ head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
if(head->File) {
Log_Log("Heap", "%sowned by %s:%i",
(head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
}
- Log_Log("Heap", "");
+ #endif
// Sanity Check Header
if(head->Size == 0) {
break;
}
+ #if VERBOSE_DUMP
+ Log_Log("Heap", "");
+ #endif
+
// All OK? Go to next
head = foot->NextHead;
}
+ // If the heap is valid, ok!
+ if( (tVAddr)head == (tVAddr)gHeapEnd )
+ return ;
+
// Check for a bad return
if( (tVAddr)head >= (tVAddr)gHeapEnd )
return ;
+
+ #if !VERBOSE_DUMP
+ Log_Log("Heap", "%p (0x%llx): 0x%08lx %i %4C",
+ head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
+ Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
+ if(head->File) {
+ Log_Log("Heap", "%sowned by %s:%i",
+ (head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
+ }
+ Log_Log("Heap", "");
+ #endif
- badHead = head;
- Log_Log("Heap", "==== Going Backwards ==== (from %p)", badHead);
+ badHead = head;
// Work backwards
foot = (void*)( (tVAddr)gHeapEnd - sizeof(tHeapFoot) );
+ Log_Log("Heap", "==== Going Backwards ==== (from %p)", foot);
head = foot->Head;
while( (tVAddr)head >= (tVAddr)badHead )
{
- Log_Log("Heap", "%p (0x%llx): 0x%08lx %4C",
- head, MM_GetPhysAddr((Uint)head), head->Size, &head->Magic);
+ Log_Log("Heap", "%p (0x%llx): 0x%08lx %i %4C",
+ head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
if(head->File)
Log_Log("Heap", "%sowned by %s:%i",
head = foot->Head;
Log_Debug("Heap", "head=%p", head);
}
+
+ Panic("Heap_Dump - Heap is corrupted, kernel panic!");
}
#endif
// Print the block info?
#if 1
- Log_Debug("Heap", "%p - 0x%x Owned by %s:%i",
- head, head->Size, head->File, head->Line);
+ if( head->Magic == MAGIC_FREE )
+ Log_Debug("Heap", "%p (0x%llx) - 0x%x free",
+ head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size);
+ else
+ Log_Debug("Heap", "%p (0x%llx) - 0x%x (%i) Owned by %s:%i",
+ head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size, head->ValidSize, head->File, head->Line);
#endif
}