Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / Kernel / heap.c
diff --git a/Kernel/heap.c b/Kernel/heap.c
deleted file mode 100644 (file)
index 6d099b3..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * AcessOS Microkernel Version
- * heap.c
- */
-#include <acess.h>
-#include <mm_virt.h>
-#include <heap_int.h>
-
-#define WARNINGS       1
-#define        DEBUG_TRACE     0
-#define        VERBOSE_DUMP    0
-
-// === CONSTANTS ===
-#define        HEAP_INIT_SIZE  0x8000  // 32 KiB
-#define        MIN_SIZE        (sizeof(void*))*8       // 8 Machine Words
-#define        POW2_SIZES      0
-#define        COMPACT_HEAP    0       // Use 4 byte header?
-#define        FIRST_FIT       0
-
-//#define      MAGIC_FOOT      0x2ACE5505
-//#define      MAGIC_FREE      0xACE55000
-//#define      MAGIC_USED      0x862B0505      // MAGIC_FOOT ^ MAGIC_FREE
-#define        MAGIC_FOOT      0x544F4F46      // 'FOOT'
-#define        MAGIC_FREE      0x45455246      // 'FREE'
-#define        MAGIC_USED      0x44455355      // 'USED'
-
-// === PROTOTYPES ===
-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_Dump(void);
-void   Heap_Stats(void);
-
-// === GLOBALS ===
-tMutex glHeap;
-void   *gHeapStart;
-void   *gHeapEnd;
-
-// === CODE ===
-void Heap_Install(void)
-{
-       gHeapStart      = (void*)MM_KHEAP_BASE;
-       gHeapEnd        = (void*)MM_KHEAP_BASE;
-       Heap_Extend(HEAP_INIT_SIZE);
-}
-
-/**
- * \brief Extend the size of the heap
- */
-void *Heap_Extend(int Bytes)
-{
-       Uint    i;
-       tHeapHead       *head = gHeapEnd;
-       tHeapFoot       *foot;
-       
-       // Bounds Check
-       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;
-               return NULL;
-       }
-       
-       // Heap expands in pages
-       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 = (Uint8*)gHeapEnd + (i << 12);
-       
-       // Create Block
-       head->Size = (Bytes+0xFFF)&~0xFFF;
-       head->Magic = MAGIC_FREE;
-       foot = (void*)( (Uint)gHeapEnd - sizeof(tHeapFoot) );
-       foot->Head = head;
-       foot->Magic = MAGIC_FOOT;
-       
-       return Heap_Merge(head);        // Merge with previous block
-}
-
-/**
- * \brief Merges two ajacent heap blocks
- */
-void *Heap_Merge(tHeapHead *Head)
-{
-       tHeapFoot       *foot;
-       tHeapFoot       *thisFoot;
-       tHeapHead       *head;
-       
-       //Log("Heap_Merge: (Head=%p)", Head);
-       
-       thisFoot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
-       if((Uint)thisFoot > (Uint)gHeapEnd)     return NULL;
-       
-       // Merge Left (Down)
-       foot = (void*)( (Uint)Head - sizeof(tHeapFoot) );
-       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
-               Head->Magic = 0;        // Clear old head
-               Head->Size = 0;
-               Head = foot->Head;      // Save new head address
-               foot->Head = NULL;      // Clear central footer
-               foot->Magic = 0;
-       }
-       
-       // Merge Right (Upwards)
-       head = (void*)( (Uint)Head + Head->Size );
-       if((Uint)head < (Uint)gHeapEnd && head->Magic == MAGIC_FREE)
-       {
-               Head->Size += head->Size;
-               foot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
-               foot->Head = Head;      // Update Backlink
-               thisFoot->Head = NULL;  // Clear old footer
-               thisFoot->Magic = 0;
-               head->Size = 0;         // Clear old header
-               head->Magic = 0;
-       }
-       
-       // Return new address
-       return Head;
-}
-
-/**
- * \param File Allocating source file
- * \param Line Source line
- * \param __Bytes      Size of region to allocate
- */
-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);
-       #else
-       Bytes = (__Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + MIN_SIZE-1) & ~(MIN_SIZE-1);
-       #endif
-       
-       // Lock Heap
-       Mutex_Acquire(&glHeap);
-       
-       // Traverse Heap
-       for( head = gHeapStart;
-               (Uint)head < (Uint)gHeapEnd;
-               head = (void*)((Uint)head + head->Size)
-               )
-       {
-               // Alignment Check
-               #if POW2_SIZES
-               if( head->Size != 1UUL << LOG2(head->Size) ) {
-               #else
-               if( head->Size & (MIN_SIZE-1) ) {
-               #endif
-                       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();
-                       #endif
-                       return NULL;
-               }
-               
-               // Check if allocated
-               if(head->Magic == MAGIC_USED)   continue;
-               // Error check
-               if(head->Magic != MAGIC_FREE)   {
-                       Mutex_Release(&glHeap); // Release spinlock
-                       #if WARNINGS
-                       Log_Warning("Heap", "Magic of heap address %p is invalid (%p = 0x%x)",
-                               head, &head->Magic, head->Magic);
-                       Heap_Dump();
-                       #endif
-                       return NULL;
-               }
-               
-               // Size check
-               if(head->Size < Bytes)  continue;
-               
-               // Perfect fit
-               if(head->Size == Bytes) {
-                       head->Magic = MAGIC_USED;
-                       head->File = File;
-                       head->Line = Line;
-                       head->ValidSize = __Bytes;
-                       head->AllocateTime = now();
-                       Mutex_Release(&glHeap); // Release spinlock
-                       #if DEBUG_TRACE
-                       Debug("[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
-               #if FIRST_FIT
-               best = head;
-               bestSize = head->Size;
-               break;
-               #else
-               // or check if the block is the best size
-               if(bestSize > head->Size) {
-                       best = head;
-                       bestSize = head->Size;
-               }
-               #endif
-       }
-       
-       // If no block large enough is found, create one
-       if(!best)
-       {
-               best = Heap_Extend( Bytes );
-               // Check for errors
-               if(!best) {
-                       Mutex_Release(&glHeap); // Release spinlock
-                       return NULL;
-               }
-               // Check size
-               if(best->Size == Bytes) {
-                       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
-                       Debug("[Heap   ] Malloc'd %p (%i bytes), returning to %s:%i", best->Data, best->Size, File, Line);
-                       #endif
-                       return best->Data;
-               }
-       }
-       
-       // Split Block
-       newhead = (void*)( (Uint)best + Bytes );
-       newfoot = (void*)( (Uint)best + Bytes - sizeof(tHeapFoot) );
-       foot = (void*)( (Uint)best + best->Size - sizeof(tHeapFoot) );
-       
-       newfoot->Head = best;   // Create new footer
-       newfoot->Magic = MAGIC_FOOT;
-       newhead->Size = best->Size - Bytes;     // Create new header
-       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;
-       best->AllocateTime = now();
-       
-       Mutex_Release(&glHeap); // Release spinlock
-       #if DEBUG_TRACE
-       Debug("[Heap   ] Malloc'd %p (0x%x bytes), returning to %s:%i",
-               best->Data, best->Size, File, Line);
-       #endif
-       return best->Data;
-}
-
-/**
- * \brief Free an allocated memory block
- */
-void Heap_Deallocate(void *Ptr)
-{
-       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
-       Debug("[Heap   ] free: %p freed by %p (%i old)", Ptr, __builtin_return_address(0), now()-head->AllocateTime);
-       #endif
-       
-       // Alignment Check
-       if( (Uint)Ptr & (sizeof(Uint)-1) ) {
-               Log_Warning("Heap", "free - Passed a non-aligned address (%p)", Ptr);
-               return;
-       }
-       
-       // Sanity check
-       if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
-       {
-               Log_Warning("Heap", "free - Passed a non-heap address by %p (%p < %p < %p)\n",
-                       __builtin_return_address(0), gHeapStart, Ptr, gHeapEnd);
-               return;
-       }
-       
-       // Check memory block - Header
-       head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
-       if(head->Magic == MAGIC_FREE) {
-               Log_Warning("Heap", "free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
-               return;
-       }
-       if(head->Magic != MAGIC_USED) {
-               Log_Warning("Heap", "free - Magic value is invalid (%p, 0x%x)", head, head->Magic);
-               Log_Notice("Heap", "Allocated by %s:%i", head->File, head->Line);
-               return;
-       }
-       
-       // Check memory block - Footer
-       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 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 by %s:%i", head->File, head->Line);
-               return;
-       }
-       
-       // Lock
-       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
-       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-sizeof(tHeapHead) );
-       tHeapHead       *nextHead;
-       tHeapFoot       *foot;
-       Uint    newSize = (__size + sizeof(tHeapFoot)+sizeof(tHeapHead)+MIN_SIZE-1)&~(MIN_SIZE-1);
-       
-       // Check for reallocating NULL
-       if(__ptr == NULL)       return Heap_Allocate(File, Line, __size);
-       
-       // Check if resize is needed
-       if(newSize <= head->Size)       return __ptr;
-       
-       // Check if next block is free
-       nextHead = (void*)( (Uint)head + head->Size );
-       
-       // Extend into next block
-       if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
-       {
-               Uint    size = nextHead->Size + head->Size;
-               foot = (void*)( (Uint)nextHead + nextHead->Size - sizeof(tHeapFoot) );
-               // Exact Fit
-               if(size == newSize) {
-                       head->Size = newSize;
-                       head->ValidSize = __size;
-                       head->File = File;
-                       head->Line = Line;
-                       foot->Head = head;
-                       nextHead->Magic = 0;
-                       nextHead->Size = 0;
-                       return __ptr;
-               }
-               // Create a new heap block
-               nextHead = (void*)( (Uint)head + newSize );
-               nextHead->Size = size - newSize;
-               nextHead->Magic = MAGIC_FREE;
-               foot->Head = nextHead;  // Edit 2nd footer
-               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;
-               foot->Magic = MAGIC_FOOT;
-               return __ptr;
-       }
-       
-       // Extend downwards?
-       foot = (void*)( (Uint)head - sizeof(tHeapFoot) );
-       nextHead = foot->Head;
-       if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
-       {
-               Uint    size = nextHead->Size + head->Size;
-               // Inexact fit, split things up
-               if(size > newSize)
-               {
-                       // TODO
-                       Warning("[Heap   ] TODO: Space efficient realloc when new size is smaller");
-               }
-               
-               // Exact fit
-               if(size >= newSize)
-               {
-                       Uint    oldDataSize;
-                       // Set 1st (new/lower) header
-                       nextHead->Magic = MAGIC_USED;
-                       nextHead->Size = newSize;
-                       nextHead->File = File;
-                       nextHead->Line = Line;
-                       nextHead->ValidSize = __size;
-                       // Get 2nd (old) footer
-                       foot = (void*)( (Uint)nextHead + newSize );
-                       foot->Head = nextHead;
-                       // Save old data size
-                       oldDataSize = head->Size - sizeof(tHeapFoot) - sizeof(tHeapHead);
-                       // Clear old header
-                       head->Size = 0;
-                       head->Magic = 0;
-                       // Copy data
-                       memcpy(nextHead->Data, __ptr, oldDataSize);
-                       // Return
-                       return nextHead->Data;
-               }
-               // On to the expensive then
-       }
-       
-       // Well, darn
-       nextHead = Heap_Allocate( File, Line, __size );
-       nextHead -= 1;
-       nextHead->File = File;
-       nextHead->Line = Line;
-       nextHead->ValidSize = __size;
-       
-       memcpy(
-               nextHead->Data,
-               __ptr,
-               head->Size - sizeof(tHeapFoot) - sizeof(tHeapHead)
-               );
-       
-       free(__ptr);
-       
-       return nextHead->Data;
-}
-
-/**
- * \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 Bytes        Size of the allocation
- */
-void *Heap_AllocateZero(const char *File, int Line, size_t Bytes)
-{
-       void    *ret = Heap_Allocate(File, Line, Bytes);
-       if(ret == NULL) return NULL;
-       
-       memset( ret, 0, Bytes );
-       
-       return ret;
-}
-
-/**
- * \fn int Heap_IsHeapAddr(void *Ptr)
- * \brief Checks if an address is a heap pointer
- */
-int Heap_IsHeapAddr(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;
-}
-
-/**
- */
-void Heap_Validate(void)
-{
-       Heap_Dump();
-}
-
-#if WARNINGS
-void Heap_Dump(void)
-{
-       tHeapHead       *head, *badHead;
-       tHeapFoot       *foot = NULL;
-       
-       head = gHeapStart;
-       while( (Uint)head < (Uint)gHeapEnd )
-       {               
-               foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
-               #if VERBOSE_DUMP
-               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",
-                               (head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
-               }
-               #endif
-               
-               // Sanity Check Header
-               if(head->Size == 0) {
-                       Log_Warning("Heap", "HALTED - Size is zero");
-                       break;
-               }
-               if(head->Size & (MIN_SIZE-1)) {
-                       Log_Warning("Heap", "HALTED - Size is malaligned");
-                       break;
-               }
-               if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
-                       Log_Warning("Heap", "HALTED - Head Magic is Bad");
-                       break;
-               }
-               
-               // Check footer
-               if(foot->Magic != MAGIC_FOOT) {
-                       Log_Warning("Heap", "HALTED - Foot Magic is Bad");
-                       break;
-               }
-               if(head != foot->Head) {
-                       Log_Warning("Heap", "HALTED - Footer backlink is invalid");
-                       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 (%P): 0x%08lx %i %4C",
-               head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->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);
-       }
-       Log_Log("Heap", "");
-       #endif
-       
-       
-       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 (%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)
-                       Log_Log("Heap", "%sowned by %s:%i",
-                               (head->Magic!=MAGIC_USED?"was ":""),
-                               head->File, head->Line);
-               Log_Log("Heap", "");
-               
-               // Sanity Check Header
-               if(head->Size == 0) {
-                       Log_Warning("Heap", "HALTED - Size is zero");
-                       break;
-               }
-               if(head->Size & (MIN_SIZE-1)) {
-                       Log_Warning("Heap", " - Size is malaligned (&0x%x)", ~(MIN_SIZE-1));
-                       break ;
-               }
-               if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
-                       Log_Warning("Heap", "HALTED - Head Magic is Bad");
-                       break;
-               }
-               
-               // Check footer
-               if(foot->Magic != MAGIC_FOOT) {
-                       Log_Warning("Heap", "HALTED - Foot Magic is Bad");
-                       break;
-               }
-               if(head != foot->Head) {
-                       Log_Warning("Heap", "HALTED - Footer backlink is invalid");
-                       break;
-               }
-               
-               if(head == badHead)     break;
-               
-               foot = (void*)( (tVAddr)head - sizeof(tHeapFoot) );
-               head = foot->Head;
-               Log_Debug("Heap", "head=%p", head);
-       }
-       
-       Panic("Heap_Dump - Heap is corrupted, kernel panic!");
-}
-#endif
-
-#if 1
-void Heap_Stats(void)
-{
-       tHeapHead       *head;
-        int    nBlocks = 0;
-        int    nFree = 0;
-        int    totalBytes = 0;
-        int    freeBytes = 0;
-        int    maxAlloc=0, minAlloc=-1;
-        int    avgAlloc, frag, overhead;
-       
-       for(head = gHeapStart;
-               (Uint)head < (Uint)gHeapEnd;
-               head = (void*)( (Uint)head + head->Size )
-               )
-       {       
-               nBlocks ++;
-               totalBytes += head->Size;
-               if( head->Magic == MAGIC_FREE )
-               {
-                       nFree ++;
-                       freeBytes += head->Size;
-               }
-               else if( head->Magic == MAGIC_USED) {
-                       if(maxAlloc < head->Size)       maxAlloc = head->Size;
-                       if(minAlloc == -1 || minAlloc > head->Size)
-                               minAlloc = head->Size;
-               }
-               else {
-                       Log_Warning("Heap", "Magic on %p invalid, skipping remainder of heap", head);
-                       break;
-               }
-               
-               // Print the block info?
-               #if 1
-               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);
-       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);
-       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
-               );
-       Log_Log("Heap", "Smallest Block: %i bytes, Largest: %i bytes", 
-               minAlloc, maxAlloc);
-       
-       // Scan and get distribution
-       #if 1
-       {
-               struct {
-                       Uint    Size;
-                       Uint    Count;
-               }       sizeCounts[nBlocks];
-                int    i;
-               
-               memset(sizeCounts, 0, nBlocks*sizeof(sizeCounts[0]));
-               
-               for(head = gHeapStart;
-                       (Uint)head < (Uint)gHeapEnd;
-                       head = (void*)( (Uint)head + head->Size )
-                       )
-               {
-                       for( i = 0; i < nBlocks; i ++ ) {
-                               if( sizeCounts[i].Size == 0 )
-                                       break;
-                               if( sizeCounts[i].Size == head->Size )
-                                       break;
-                       }
-                       // Should never reach this part (in a non-concurrent case)
-                       if( i == nBlocks )      continue;
-                       sizeCounts[i].Size = head->Size;
-                       sizeCounts[i].Count ++;
-                       #if 1
-                       //Log("Heap_Stats: %i %p - 0x%x bytes (%s) (%i)", nBlocks, head,
-                       //      head->Size, (head->Magic==MAGIC_FREE?"FREE":"used"), i
-                       //      );
-                       //Log("Heap_Stats: sizeCounts[%i] = {Size:0x%x, Count: %i}", i,
-                       //      sizeCounts[i].Size, sizeCounts[i].Count);
-                       #endif
-               }
-               
-               for( i = 0; i < nBlocks && sizeCounts[i].Count; i ++ )
-               {
-                       Log("Heap_Stats: 0x%x - %i blocks",
-                               sizeCounts[i].Size, sizeCounts[i].Count
-                               );
-               }
-       }
-       #endif
-}
-#endif
-
-// === EXPORTS ===
-EXPORT(Heap_Allocate);
-EXPORT(Heap_AllocateZero);
-EXPORT(Heap_Reallocate);
-EXPORT(Heap_Deallocate);
-EXPORT(Heap_IsHeapAddr);

UCC git Repository :: git.ucc.asn.au