X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fheap.c;h=47de8be5894504e2409b350cc37007cb163d83af;hb=24a52dc748126b1449a104c7f756b201c8ac1b02;hp=eefd13cf22e6c690e65fcd9702c05846018cdd92;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/heap.c b/KernelLand/Kernel/heap.c index eefd13cf..47de8be5 100644 --- a/KernelLand/Kernel/heap.c +++ b/KernelLand/Kernel/heap.c @@ -1,14 +1,17 @@ /* - * AcessOS Microkernel Version + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * * heap.c + * - Dynamic memory allocation */ #include #include #include -#define WARNINGS 1 -#define DEBUG_TRACE 0 -#define VERBOSE_DUMP 0 +#define WARNINGS 1 // Warn and dump on heap errors +#define DEBUG_TRACE 0 // Enable tracing of allocations +#define VERBOSE_DUMP 0 // Set to 1 to enable a verbose dump when heap errors are encountered // === CONSTANTS === #define HEAP_INIT_SIZE 0x8000 // 32 KiB @@ -26,64 +29,70 @@ // === PROTOTYPES === void Heap_Install(void); -void *Heap_Extend(int Bytes); +void *Heap_Extend(size_t 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_Deallocate(const char *File, int Line, void *Ptr); +void Heap_Dump(int bVerbose); void Heap_Stats(void); // === GLOBALS === tMutex glHeap; -void *gHeapStart; -void *gHeapEnd; +tHeapHead *gHeapStart; +tHeapHead *gHeapEnd; // === CODE === void Heap_Install(void) { - gHeapStart = (void*)MM_KHEAP_BASE; - gHeapEnd = (void*)MM_KHEAP_BASE; + gHeapStart = (void*)MM_KHEAP_BASE; + gHeapEnd = gHeapStart; Heap_Extend(HEAP_INIT_SIZE); } /** * \brief Extend the size of the heap */ -void *Heap_Extend(int Bytes) +void *Heap_Extend(size_t Bytes) { - Uint i; tHeapHead *head = gHeapEnd; tHeapFoot *foot; // Bounds Check - if( (tVAddr)gHeapEnd == MM_KHEAP_MAX ) + if( gHeapEnd == (tHeapHead*)MM_KHEAP_MAX ) { + Log_Error("Heap", "Heap limit reached (%p)", (void*)MM_KHEAP_MAX); return NULL; + } if( Bytes == 0 ) { Log_Warning("Heap", "Heap_Extend called with Bytes=%i", Bytes); return NULL; } + const Uint pages = (Bytes + 0xFFF) >> 12; + tHeapHead *new_end = (void*)( (tVAddr)gHeapEnd + (pages << 12) ); // Bounds Check - if( (tVAddr)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) { -// Bytes = MM_KHEAP_MAX - (tVAddr)gHeapEnd; + if( new_end > (tHeapHead*)MM_KHEAP_MAX ) + { + Log_Error("Heap", "Heap limit exceeded (%p)", (void*)new_end); + // TODO: Clip allocation to avaliable space, and have caller check returned block return NULL; } // Heap expands in pages - for( i = 0; i < (Bytes+0xFFF) >> 12; i ++ ) + for( Uint i = 0; i < pages; i ++ ) { if( !MM_Allocate( (tVAddr)gHeapEnd+(i<<12) ) ) { Warning("OOM - Heap_Extend"); + Heap_Dump(1); return NULL; } } - // Increas heap end - gHeapEnd = (Uint8*)gHeapEnd + (i << 12); + // Increase heap end + gHeapEnd = new_end; // Create Block head->Size = (Bytes+0xFFF)&~0xFFF; @@ -153,8 +162,8 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) size_t Bytes; if( __Bytes == 0 ) { - //return NULL; // TODO: Return a known un-mapped range. - return INVLPTR; + return NULL; // TODO: Return a known un-mapped range. +// return INVLPTR; } // Get required size @@ -169,10 +178,7 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) Mutex_Acquire(&glHeap); // Traverse Heap - for( head = gHeapStart; - (Uint)head < (Uint)gHeapEnd; - head = (void*)((Uint)head + head->Size) - ) + for( head = gHeapStart; head < gHeapEnd; head = (void*)((Uint)head + head->Size) ) { // Alignment Check #if POW2_SIZES @@ -182,11 +188,26 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) #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(); + Log_Warning("Heap", "Size of heap address %p is invalid - not aligned (0x%x) [at paddr 0x%x]", + head, head->Size, MM_GetPhysAddr(&head->Size)); + Heap_Dump(VERBOSE_DUMP); #endif return NULL; } + if( head->Size < MIN_SIZE ) { + Mutex_Release(&glHeap); + Log_Warning("Heap", "Size of heap address %p is invalid - Too small (0x%x) [at paddr 0x%x]", + head, head->Size, MM_GetPhysAddr(&head->Size)); + Heap_Dump(VERBOSE_DUMP); + return NULL; + } + if( head->Size > (2<<30) ) { + Mutex_Release(&glHeap); + Log_Warning("Heap", "Size of heap address %p is invalid - Over 2GiB (0x%x) [at paddr 0x%x]", + head, head->Size, MM_GetPhysAddr(&head->Size)); + Heap_Dump(VERBOSE_DUMP); + return NULL; + } // Check if allocated if(head->Magic == MAGIC_USED) continue; @@ -196,7 +217,7 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) #if WARNINGS Log_Warning("Heap", "Magic of heap address %p is invalid (%p = 0x%x)", head, &head->Magic, head->Magic); - Heap_Dump(); + Heap_Dump(VERBOSE_DUMP); #endif return NULL; } @@ -213,8 +234,8 @@ void *Heap_Allocate(const char *File, int Line, size_t __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)); + Log_Debug("Heap", "Malloc'd %p (0x%x bytes), returning to %s:%i", + head->Data, head->Size, File, Line); #endif return head->Data; } @@ -251,7 +272,8 @@ void *Heap_Allocate(const char *File, int Line, size_t __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); + Log_Debug("Heap", "Malloc'd %p (0x%x bytes), returning to %s:%i", + best->Data, best->Size, File, Line); #endif return best->Data; } @@ -276,7 +298,7 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) Mutex_Release(&glHeap); // Release spinlock #if DEBUG_TRACE - Debug("[Heap ] Malloc'd %p (0x%x bytes), returning to %s:%i", + Log_Debug("Heap", "Malloc'd %p (0x%x bytes), returning to %s:%i", best->Data, best->Size, File, Line); #endif return best->Data; @@ -285,7 +307,7 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) /** * \brief Free an allocated memory block */ -void Heap_Deallocate(void *Ptr) +void Heap_Deallocate(const char *File, int Line, void *Ptr) { tHeapHead *head = (void*)( (Uint)Ptr - sizeof(tHeapHead) ); tHeapFoot *foot; @@ -294,10 +316,6 @@ void Heap_Deallocate(void *Ptr) // 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); @@ -307,7 +325,7 @@ void Heap_Deallocate(void *Ptr) // 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", + Log_Warning("Heap", "free - Passed a non-heap address by %p (%p < %p < %p)", __builtin_return_address(0), gHeapStart, Ptr, gHeapEnd); return; } @@ -315,7 +333,9 @@ void Heap_Deallocate(void *Ptr) // 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)); + Log_Warning("Heap", "free - Passed a freed block (%p) by %s:%i (was freed by %s:%i)", + head, File, Line, + head->File, head->Line); return; } if(head->Magic != MAGIC_USED) { @@ -337,13 +357,18 @@ void Heap_Deallocate(void *Ptr) return; } + #if DEBUG_TRACE + Log_Debug("Heap", "free: %p freed by %s:%i (%i old)", + Ptr, File, Line, now()-head->AllocateTime); + #endif + // Lock Mutex_Acquire( &glHeap ); // Mark as free head->Magic = MAGIC_FREE; - //head->File = NULL; - //head->Line = 0; + head->File = File; + head->Line = Line; head->ValidSize = 0; // Merge blocks Heap_Merge( head ); @@ -448,6 +473,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) // Well, darn nextHead = Heap_Allocate( File, Line, __size ); + if(!nextHead) return NULL; nextHead -= 1; nextHead->File = File; nextHead->Line = Line; @@ -503,28 +529,36 @@ int Heap_IsHeapAddr(void *Ptr) */ void Heap_Validate(void) { - Heap_Dump(); + // Call dump non-verbosely. + // - If a heap error is detected, it'll print + Heap_Dump(0); } -#if WARNINGS -void Heap_Dump(void) +void Heap_Dump(int bVerbose) { tHeapHead *head, *badHead; tHeapFoot *foot = NULL; + static int in_heap_dump; + if( in_heap_dump ) return; + + in_heap_dump = 1; + 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); + + if( bVerbose ) + { + Log_Log("Heap", "%p (0x%P): 0x%08x (%i) %4C", + head, MM_GetPhysAddr(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) { @@ -550,33 +584,40 @@ void Heap_Dump(void) break; } - #if VERBOSE_DUMP - Log_Log("Heap", ""); - #endif + if( bVerbose ) + { + Log_Log("Heap", ""); + } // All OK? Go to next head = foot->NextHead; } // If the heap is valid, ok! - if( (tVAddr)head == (tVAddr)gHeapEnd ) + if( (tVAddr)head == (tVAddr)gHeapEnd ) { + in_heap_dump = 0; return ; + } // Check for a bad return - if( (tVAddr)head >= (tVAddr)gHeapEnd ) + if( (tVAddr)head >= (tVAddr)gHeapEnd ) { + in_heap_dump = 0; 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); + // If not verbose, we need to dump the failing block + if( !bVerbose ) + { + Log_Log("Heap", "%p (%P): 0x%08lx %i %4C", + head, MM_GetPhysAddr(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", ""); } - Log_Log("Heap", ""); - #endif badHead = head; @@ -588,7 +629,7 @@ void Heap_Dump(void) 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); + head, MM_GetPhysAddr(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", @@ -629,12 +670,9 @@ void Heap_Dump(void) 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; @@ -642,10 +680,7 @@ void Heap_Stats(void) int maxAlloc=0, minAlloc=-1; int avgAlloc, frag, overhead; - for(head = gHeapStart; - (Uint)head < (Uint)gHeapEnd; - head = (void*)( (Uint)head + head->Size ) - ) + for(tHeapHead *head = gHeapStart; head < gHeapEnd; head = (void*)( (tVAddr)head + head->Size ) ) { nBlocks ++; totalBytes += head->Size; @@ -668,10 +703,11 @@ void Heap_Stats(void) #if 1 if( head->Magic == MAGIC_FREE ) Log_Debug("Heap", "%p (%P) - 0x%x free", - head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size); + head->Data, MM_GetPhysAddr(&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, + head->Data, MM_GetPhysAddr(&head->Data), head->Size, + head->ValidSize, head->File, head->Line, now() - head->AllocateTime ); #endif @@ -710,10 +746,7 @@ void Heap_Stats(void) memset(sizeCounts, 0, nBlocks*sizeof(sizeCounts[0])); - for(head = gHeapStart; - (Uint)head < (Uint)gHeapEnd; - head = (void*)( (Uint)head + head->Size ) - ) + for(tHeapHead *head = gHeapStart; head < gHeapEnd; head = (void*)( (tVAddr)head + head->Size ) ) { for( i = 0; i < nBlocks; i ++ ) { if( sizeCounts[i].Size == 0 ) @@ -725,12 +758,12 @@ void Heap_Stats(void) 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); + #if 0 + 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 } @@ -743,7 +776,6 @@ void Heap_Stats(void) } #endif } -#endif // === EXPORTS === EXPORT(Heap_Allocate);