X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fheap.c;h=f7054ea4375684ed981eb729d26ce875c183f606;hb=7efc14b23fca7b88126f27d34e99d7e8046e817a;hp=20729d8a17eefede82a393ad2d8440819f665ecf;hpb=bc136caef26bc1399cb03b9bee03b648f871166e;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/heap.c b/KernelLand/Kernel/heap.c index 20729d8a..f7054ea4 100755 --- a/KernelLand/Kernel/heap.c +++ b/KernelLand/Kernel/heap.c @@ -9,6 +9,7 @@ #include #include #include +#include #define WARNINGS 1 // Warn and dump on heap errors #define DEBUG_TRACE 0 // Enable tracing of allocations @@ -33,12 +34,16 @@ void Heap_Install(void); void *Heap_Extend(size_t Bytes); void *Heap_Merge(tHeapHead *Head); +static const size_t Heap_int_GetBlockSize(size_t AllocSize); //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(const char *File, int Line, void *Ptr); -void Heap_Dump(int bVerbose); -void Heap_Stats(void); + int Heap_int_ApplyWatchpont(void *Addr, bool Enabled); +void Heap_int_WatchBlock(tHeapHead *Head, bool Enabled); +//void Heap_Dump(void); +void Heap_ValidateDump(int bVerbose); +//void Heap_Stats(void); // === GLOBALS === tMutex glHeap; @@ -69,7 +74,7 @@ static inline tHeapFoot *Heap_PrevFoot(tHeapHead *Head) { */ void *Heap_Extend(size_t Bytes) { - Debug("Heap_Extend(0x%x)", Bytes); + //Debug("Heap_Extend(0x%x)", Bytes); // Bounds Check if( gHeapEnd == (tHeapHead*)MM_KHEAP_MAX ) { @@ -95,10 +100,10 @@ void *Heap_Extend(size_t Bytes) // Heap expands in pages for( Uint i = 0; i < pages; i ++ ) { - if( !MM_Allocate( (tVAddr)gHeapEnd+(i<<12) ) ) + if( !MM_Allocate( (tPage*)gHeapEnd + i ) ) { Warning("OOM - Heap_Extend (%i bytes)"); - Heap_Dump(1); + Heap_Dump(); return NULL; } } @@ -122,20 +127,15 @@ void *Heap_Extend(size_t Bytes) */ void *Heap_Merge(tHeapHead *Head) { - tHeapFoot *foot; - tHeapFoot *thisFoot; - tHeapHead *head; - //Log("Heap_Merge: (Head=%p)", Head); + tHeapFoot *thisFoot = Heap_ThisFoot(Head); - thisFoot = Heap_ThisFoot(Head); - if( (void*)thisFoot > (void*)gHeapEnd ) - return NULL; + ASSERT( Heap_NextHead(Head) <= gHeapEnd ); // Merge Left (Down) - foot = Heap_PrevFoot(Head); - if( ((Uint)foot < (Uint)gHeapEnd && (Uint)foot > (Uint)gHeapStart) - && foot->Head->Magic == MAGIC_FREE) { + tHeapFoot *foot = Heap_PrevFoot(Head); + if( Head > 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 @@ -146,22 +146,34 @@ void *Heap_Merge(tHeapHead *Head) } // Merge Right (Upwards) - head = Heap_NextHead(Head); - if((Uint)head < (Uint)gHeapEnd && head->Magic == MAGIC_FREE) + tHeapHead *nexthead = Heap_NextHead(Head); + if(nexthead < gHeapEnd && nexthead->Magic == MAGIC_FREE) { - Head->Size += head->Size; + Head->Size += nexthead->Size; foot = Heap_ThisFoot(Head); foot->Head = Head; // Update Backlink thisFoot->Head = NULL; // Clear old footer thisFoot->Magic = 0; - head->Size = 0; // Clear old header - head->Magic = 0; + nexthead->Size = 0; // Clear old header + nexthead->Magic = 0; } // Return new address return Head; } +static const size_t Heap_int_GetBlockSize(size_t AllocSize) +{ + size_t Bytes; + #if POW2_SIZES + Bytes = AllocSize + sizeof(tHeapHead) + sizeof(tHeapFoot); + Bytes = 1UUL << LOG2(Bytes); + #else + Bytes = (AllocSize + sizeof(tHeapHead) + sizeof(tHeapFoot) + MIN_SIZE-1) & ~(MIN_SIZE-1); + #endif + return Bytes; +} + /** * \param File Allocating source file * \param Line Source line @@ -181,16 +193,11 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) } #if VALIDATE_ON_ALLOC - Heap_Dump(0); + Heap_Validate(); #endif // 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 + Bytes = Heap_int_GetBlockSize(__Bytes); // Lock Heap Mutex_Acquire(&glHeap); @@ -209,24 +216,28 @@ void *Heap_Allocate(const char *File, int Line, size_t __Bytes) 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); + Heap_ValidateDump(VERBOSE_DUMP); #endif return NULL; } if( head->Size < MIN_SIZE ) { Mutex_Release(&glHeap); + #if WARNINGS 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); + Heap_ValidateDump(VERBOSE_DUMP); + #endif return NULL; } if( head->Size > (2<<30) ) { Mutex_Release(&glHeap); + #if WARNINGS 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); + Heap_ValidateDump(VERBOSE_DUMP); + #endif return NULL; } @@ -238,7 +249,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(VERBOSE_DUMP); + Heap_ValidateDump(VERBOSE_DUMP); #endif return NULL; } @@ -358,7 +369,7 @@ void Heap_Deallocate(const char *File, int Line, void *Ptr) } // Check memory block - Header - tHeapHead *head = (void*)( (Uint)Ptr - sizeof(tHeapHead) ); + tHeapHead *head = (tHeapHead*)Ptr - 1; if(head->Magic == MAGIC_FREE) { Log_Warning("Heap", "free - Passed a freed block (%p) by %s:%i (was freed by %s:%i)", head, File, Line, @@ -393,7 +404,9 @@ void Heap_Deallocate(const char *File, int Line, void *Ptr) // Lock Mutex_Acquire( &glHeap ); - + + Heap_int_WatchBlock(head, false); + // Mark as free head->Magic = MAGIC_FREE; head->File = File; @@ -415,16 +428,36 @@ void Heap_Deallocate(const char *File, int Line, void *Ptr) */ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) { - tHeapHead *head = (void*)( (Uint)__ptr-sizeof(tHeapHead) ); + tHeapHead *head = (tHeapHead*)__ptr - 1; tHeapHead *nextHead; tHeapFoot *foot; - Uint newSize = (__size + sizeof(tHeapFoot)+sizeof(tHeapHead)+MIN_SIZE-1)&~(MIN_SIZE-1); + Uint newSize = Heap_int_GetBlockSize(__size); // Check for reallocating NULL - if(__ptr == NULL) return Heap_Allocate(File, Line, __size); + if(__ptr == NULL) + return Heap_Allocate(File, Line, __size); + + if( !Heap_IsHeapAddr(__ptr)) { + Log_Error("Heap", "%s:%i passed non-heap address %p when reallocating to %zi", + File, Line, __ptr, __size); + return NULL; + } // Check if resize is needed - if(newSize <= head->Size) return __ptr; + // TODO: Reduce size of block if needed + if(newSize <= head->Size) { + #if DEBUG_TRACE + Log_Debug("Heap", "realloc maintain %p (0x%x >= 0x%x), returning to %s:%i", + head->Data, head->Size, newSize, File, Line); + #endif + return __ptr; + } + + #if VALIDATE_ON_ALLOC + Heap_Validate(); + #endif + + Heap_int_WatchBlock(head, false); // Check if next block is free nextHead = Heap_NextHead(head); @@ -432,6 +465,10 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) // Extend into next block if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize) { + #if DEBUG_TRACE + Log_Debug("Heap", "realloc expand %p (0x%x to 0x%x), returning to %s:%i", + head->Data, head->Size, newSize, File, Line); + #endif Uint size = nextHead->Size + head->Size; foot = Heap_ThisFoot(nextHead); // Exact Fit @@ -460,7 +497,7 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) nextHead->Size = size - newSize; nextHead->Magic = MAGIC_FREE; // - Update old footer - foot->Head = nextHead; + Heap_ThisFoot(nextHead)->Head = nextHead; return __ptr; } @@ -477,6 +514,11 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) Warning("[Heap ] TODO: Space efficient realloc when new size is smaller"); } + #if DEBUG_TRACE + Log_Debug("Heap", "realloc expand down %p (0x%x to 0x%x), returning to %s:%i", + head->Data, head->Size, newSize, File, Line); + #endif + // Exact fit Uint oldDataSize; // Set 1st (new/lower) header @@ -507,6 +549,8 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) nextHead->Line = Line; nextHead->ValidSize = __size; + ASSERTC(head->Size, <, nextHead->Size); + ASSERTC(__ptr, ==, head->Data); memcpy( nextHead->Data, __ptr, @@ -514,7 +558,8 @@ void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size) ); free(__ptr); - + Heap_Validate(); + return nextHead->Data; } @@ -553,16 +598,95 @@ int Heap_IsHeapAddr(void *Ptr) return 1; } +int Heap_int_ApplyWatchpont(void *Word, bool enabled) +{ + #if ARCHDIR_IS_x86 + static void *active_wps[4]; + unsigned int dr; + for( dr = 2; dr < 4; dr ++ ) + { + if( (enabled && active_wps[dr] == NULL) || active_wps[dr] == Word) + break; + } + if(dr == 4) { + return 1; + } + if( enabled ) + { + active_wps[dr] = Word; + switch(dr) + { + //case 0: ASM("mov %0, %%dr0" : : "r" (Word)); break; + //case 1: ASM("mov %0, %%dr1" : : "r" (Word)); break; + case 2: ASM("mov %0, %%dr2" : : "r" (Word)); break; + case 3: ASM("mov %0, %%dr3" : : "r" (Word)); break; + default: ASSERTC(dr,<,4); return 1; + } + } + else + { + active_wps[dr] = NULL; + } + Uint32 dr7flag; + ASM("MOV %%dr7, %0" : "=r" (dr7flag)); + dr7flag &= ~(0x2 << (dr*2)); + dr7flag &= ~(0xF000 << (dr*4)); + if( enabled ) { + dr7flag |= 0x2 << (dr*2); + dr7flag |= 0xD000 << (dr*4); // 4 bytes, write + Debug("Heap_int_ApplyWatchpont: Watchpoint #%i %p ENABLED", dr, Word); + } + else { + Debug("Heap_int_ApplyWatchpont: Watchpoint #%i %p disabled", dr, Word); + } + ASM("MOV %0, %%dr7" : : "r" (dr7flag)); + return 0; + #else + return 1; + #endif +} + +void Heap_int_WatchBlock(tHeapHead *Head, bool Enabled) +{ + int rv; + rv = Heap_int_ApplyWatchpont( &Head->Size, Enabled ); + //rv = Heap_int_ApplyWatchpont( &Head->Magic, Enabled ); + rv = rv + Heap_int_ApplyWatchpont( &Heap_ThisFoot(Head)->Head, Enabled ); + if(rv && Enabled) { + Warning("Can't apply watch on %p", Head); + } +} + +int Heap_WatchBlock(void *Ptr) +{ + //Heap_int_ApplyWatchpont(); + 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 = (tHeapHead*)Ptr - 1; + + Heap_int_WatchBlock( head, true ); + + return 0; +} + /** */ void Heap_Validate(void) { // Call dump non-verbosely. // - If a heap error is detected, it'll print - Heap_Dump(0); + Heap_ValidateDump(0); +} + +void Heap_Dump(void) +{ + Heap_ValidateDump(1); } -void Heap_Dump(int bVerbose) +void Heap_ValidateDump(int bVerbose) { tHeapHead *head, *badHead; tHeapFoot *foot = NULL;