X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fheap.c;h=a9e9931fe4ede32462c4732013b923b7e7c0b4be;hb=refs%2Ftags%2Frel0.10;hp=97f2d9f16629ed472c6ccdf19bcbc7f2dd9f349e;hpb=6a945643557084578509e149c84cf5dde3c59c3c;p=tpg%2Facess2.git diff --git a/Kernel/heap.c b/Kernel/heap.c index 97f2d9f1..a9e9931f 100644 --- a/Kernel/heap.c +++ b/Kernel/heap.c @@ -8,6 +8,7 @@ #define WARNINGS 1 #define DEBUG_TRACE 0 +#define VERBOSE_DUMP 0 // === CONSTANTS === #define HEAP_INIT_SIZE 0x8000 // 32 KiB @@ -27,15 +28,15 @@ 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; @@ -61,6 +62,11 @@ 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; @@ -68,11 +74,17 @@ void *Heap_Extend(int Bytes) } // 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; @@ -135,23 +147,29 @@ void *Heap_Merge(tHeapHead *Head) * \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; @@ -165,7 +183,7 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) #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(); @@ -177,7 +195,7 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) 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(); @@ -193,9 +211,11 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) head->Magic = MAGIC_USED; head->File = File; head->Line = Line; - RELEASE(&glHeap); // Release spinlock + 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; } @@ -220,7 +240,7 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) best = Heap_Extend( Bytes ); // Check for errors if(!best) { - RELEASE(&glHeap); // Release spinlock + Mutex_Release(&glHeap); // Release spinlock return NULL; } // Check size @@ -228,9 +248,11 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) best->Magic = MAGIC_USED; // Mark block as used best->File = File; best->Line = Line; - RELEASE(&glHeap); // Release spinlock + 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; } @@ -247,14 +269,15 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) 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(); - 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", + Debug("[Heap ] Malloc'd %p (0x%x bytes), returning to %s:%i", best->Data, best->Size, File, Line); #endif return best->Data; @@ -266,12 +289,15 @@ void *Heap_Allocate(const char *File, int Line, size_t Bytes) */ 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 @@ -296,7 +322,7 @@ void Heap_Deallocate(void *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; } @@ -304,32 +330,40 @@ void Heap_Deallocate(void *Ptr) 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); @@ -351,6 +385,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) // Exact Fit if(size == newSize) { head->Size = newSize; + head->ValidSize = __size; head->File = File; head->Line = Line; foot->Head = head; @@ -366,6 +401,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) 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; @@ -395,6 +431,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) nextHead->Size = newSize; nextHead->File = File; nextHead->Line = Line; + nextHead->ValidSize = __size; // Get 2nd (old) footer foot = (void*)( (Uint)nextHead + newSize ); foot->Head = nextHead; @@ -416,6 +453,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) nextHead -= 1; nextHead->File = File; nextHead->Line = Line; + nextHead->ValidSize = __size; memcpy( nextHead->Data, @@ -429,18 +467,18 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) } /** - * \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; } @@ -463,24 +501,32 @@ int Heap_IsHeapAddr(void *Ptr) 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) { @@ -506,25 +552,44 @@ void Heap_Dump(void) 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); + 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 (%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", @@ -562,6 +627,8 @@ void Heap_Dump(void) head = foot->Head; Log_Debug("Heap", "head=%p", head); } + + Panic("Heap_Dump - Heap is corrupted, kernel panic!"); } #endif @@ -600,8 +667,14 @@ void Heap_Stats(void) // 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 }