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);
}
/**
- * \fn void *Heap_Extend(int Bytes)
* \brief Extend the size of the heap
*/
void *Heap_Extend(int Bytes)
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;
+// Bytes = MM_KHEAP_MAX - (tVAddr)gHeapEnd;
return NULL;
}
// 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;
}
/**
- * \fn void *Heap_Merge(tHeapHead *Head)
* \brief Merges two ajacent heap blocks
*/
void *Heap_Merge(tHeapHead *Head)
}
/**
- * \brief Allocate memory from the heap
* \param File Allocating source file
* \param Line Source line
- * \param Bytes Size of region to allocate
+ * \param __Bytes Size of region to allocate
*/
void *Heap_Allocate(const char *File, int Line, size_t __Bytes)
{
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
if(head->Magic != MAGIC_FREE) {
Mutex_Release(&glHeap); // Release spinlock
#if WARNINGS
- Log_Warning("Heap", "Magic of heap address %p is invalid (0x%x)", head, head->Magic);
+ Log_Warning("Heap", "Magic of heap address %p is invalid (%p = 0x%x)",
+ head, &head->Magic, head->Magic);
Heap_Dump();
#endif
return NULL;
head->Magic = MAGIC_USED;
head->File = File;
head->Line = Line;
+ head->ValidSize = __Bytes;
+ head->AllocateTime = now();
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));
+ Debug("[Heap ] Malloc'd %p (%i bytes), returning to %p",
+ head->Data, head->Size, __builtin_return_address(0));
#endif
return head->Data;
}
best->Magic = MAGIC_USED; // Mark block as used
best->File = File;
best->Line = Line;
+ best->ValidSize = __Bytes;
+ best->AllocateTime = now();
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));
+ Debug("[Heap ] Malloc'd %p (%i bytes), returning to %s:%i", best->Data, best->Size, File, Line);
#endif
return best->Data;
}
best->Magic = MAGIC_USED; // Mark block as used
best->File = File;
best->Line = Line;
+ best->AllocateTime = now();
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",
+ Debug("[Heap ] Malloc'd %p (0x%x bytes), returning to %s:%i",
best->Data, best->Size, File, Line);
#endif
return best->Data;
}
/**
- * \fn void Heap_Deallocate(void *Ptr)
* \brief Free an allocated memory block
*/
void Heap_Deallocate(void *Ptr)
{
- tHeapHead *head;
+ tHeapHead *head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
tHeapFoot *foot;
+ // INVLPTR is returned from Heap_Allocate when the allocation
+ // size is zero.
+ if( Ptr == INVLPTR ) return;
+
#if DEBUG_TRACE
- Log_Log("Heap", "free: Ptr = %p", Ptr);
- Log_Log("Heap", "free: Returns to %p", __builtin_return_address(0));
+ Debug("[Heap ] free: %p freed by %p (%i old)", Ptr, __builtin_return_address(0), now()-head->AllocateTime);
#endif
// Alignment Check
// Sanity check
if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
{
- Log_Warning("Heap", "free - Passed a non-heap address (%p < %p < %p)\n",
- gHeapStart, Ptr, gHeapEnd);
+ Log_Warning("Heap", "free - Passed a non-heap address by %p (%p < %p < %p)\n",
+ __builtin_return_address(0), gHeapStart, Ptr, gHeapEnd);
return;
}
}
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;
}
{
foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
#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 (0x%P): 0x%08x (%i) %4C",
+ head, MM_GetPhysAddr((tVAddr)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",
return ;
#if !VERBOSE_DUMP
- Log_Log("Heap", "%p (0x%llx): 0x%08lx (%i) %4C",
+ Log_Log("Heap", "%p (%P): 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(foot)
+ Log_Log("Heap", "Foot %p = {Head:%p,Magic:%4C}", foot, foot->Head, &foot->Magic);
if(head->File) {
Log_Log("Heap", "%sowned by %s:%i",
(head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
head = foot->Head;
while( (tVAddr)head >= (tVAddr)badHead )
{
- Log_Log("Heap", "%p (0x%llx): 0x%08lx %i %4C",
+ Log_Log("Heap", "%p (%P): 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)
// 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 (%P) - 0x%x free",
+ head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size);
+ else
+ Log_Debug("Heap", "%p (%P) - 0x%x (%i) Owned by %s:%i (%lli ms old)",
+ head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size, head->ValidSize, head->File, head->Line,
+ now() - head->AllocateTime
+ );
#endif
}
Log_Log("Heap", "%i blocks (0x%x bytes)", nBlocks, totalBytes);
Log_Log("Heap", "%i free blocks (0x%x bytes)", nFree, freeBytes);
- frag = (nFree-1)*10000/nBlocks;
+ if(nBlocks != 0)
+ frag = (nFree-1)*10000/nBlocks;
+ else
+ frag = 0;
Log_Log("Heap", "%i.%02i%% Heap Fragmentation", frag/100, frag%100);
- avgAlloc = (totalBytes-freeBytes)/(nBlocks-nFree);
- overhead = (sizeof(tHeapFoot)+sizeof(tHeapHead))*10000/avgAlloc;
+ if(nBlocks <= nFree)
+ avgAlloc = 0;
+ else
+ avgAlloc = (totalBytes-freeBytes)/(nBlocks-nFree);
+ if(avgAlloc != 0)
+ overhead = (sizeof(tHeapFoot)+sizeof(tHeapHead))*10000/avgAlloc;
+ else
+ overhead = 0;
Log_Log("Heap", "Average allocation: %i bytes, Average Overhead: %i.%02i%%",
avgAlloc, overhead/100, overhead%100
);
// Scan and get distribution
#if 1
+ if(nBlocks > 0)
{
struct {
Uint Size;