Usermode/libc - Fix time conversion code
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / heap.c
index 23df92a..71e3d6d 100644 (file)
@@ -1,40 +1,86 @@
 /*\r
-AcessOS Basic LibC\r
-heap.c - Heap Manager\r
-*/\r
+ * Acess2 C Library\r
+ * - By John Hodge (thePowersGang)\r
+ *\r
+ * heap.c\r
+ * - Dynamic Memory (malloc/free)\r
+ */\r
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+#include <stdbool.h>\r
 #include "lib.h"\r
 \r
+#if 0\r
+# define DEBUGS(s...)  _SysDebug(s)\r
+#else\r
+# define DEBUGS(s...)  do{}while(0)\r
+#endif\r
+\r
 // === Constants ===\r
 #define MAGIC  0xACE55051      //AcessOS1\r
 #define MAGIC_FREE     (~MAGIC)\r
 #define BLOCK_SIZE     16      //Minimum\r
 #define HEAP_INIT_SIZE 0x10000\r
+#define DEBUG_HEAP     1\r
 \r
 typedef unsigned int Uint;\r
 \r
-//Typedefs\r
+// === TYPES ===\r
 typedef struct {\r
-       Uint    magic;\r
-       Uint    size;\r
+       uint32_t        magic;\r
+       size_t  size;\r
+       // - \r
+       #if DEBUG_HEAP\r
+       void    *Caller;\r
+       size_t  RealSize;\r
+       #endif\r
+       char    data[];\r
 }      heap_head;\r
 typedef struct {\r
        heap_head       *header;\r
-       Uint    magic;\r
+       uint32_t        magic;\r
 }      heap_foot;\r
 \r
-//Globals\r
-void   *_heap_start = NULL;\r
-void   *_heap_end = NULL;\r
+// === HELPERS ===\r
+static inline heap_head *NEXT_HEAD(heap_head *ptr)\r
+{\r
+       return (void*)((char*)ptr + ptr->size);\r
+}\r
+static inline heap_foot *THIS_FOOT(heap_head *ptr)\r
+{\r
+       return (void*)((char*)ptr + ptr->size - sizeof(heap_foot));\r
+}\r
+static inline heap_foot *PREV_FOOT(heap_head *ptr)\r
+{\r
+       return (void*)((char*)ptr - sizeof(heap_foot));\r
+}\r
+static inline size_t CALC_BLOCK_SIZE(size_t bytes)\r
+{\r
+       size_t ret;\r
+       ret = bytes + sizeof(heap_head) + sizeof(heap_foot) + BLOCK_SIZE - 1;\r
+       ret = (ret/BLOCK_SIZE)*BLOCK_SIZE;      //Round up to block size\r
+       return ret;\r
+}\r
+\r
+// === LOCAL VARIABLES ===\r
+static heap_head       *_heap_start = NULL;\r
+static heap_head       *_heap_end = NULL;\r
+static const heap_head _heap_zero_allocation;\r
 \r
-//Prototypes\r
-EXPORT void    *malloc(Uint bytes);\r
+// === PROTOTYPES ===\r
+EXPORT void    *malloc(size_t bytes);\r
+void   *_malloc(size_t bytes, void *owner);\r
+EXPORT void    *calloc(size_t bytes, size_t count);\r
+bool   _libc_free(void *mem);\r
 EXPORT void    free(void *mem);\r
-EXPORT void    *realloc(void *mem, Uint bytes);\r
+EXPORT void    *realloc(void *mem, size_t bytes);\r
 EXPORT void    *sbrk(int increment);\r
 LOCAL void     *extendHeap(int bytes);\r
-LOCAL uint     brk(int delta);\r
+static void    *FindHeapBase();\r
+LOCAL uint     brk(uintptr_t newpos);\r
+EXPORT int     Heap_Validate(int bDump);\r
 \r
 //Code\r
 \r
@@ -46,91 +92,130 @@ LOCAL uint brk(int delta);
 */\r
 EXPORT void *malloc(size_t bytes)\r
 {\r
-       Uint    bestSize;\r
-       Uint    closestMatch = 0;\r
-       Uint    bestMatchAddr = 0;\r
-       heap_head       *curBlock;\r
-       \r
+       return _malloc(bytes, __builtin_return_address(0));\r
+}\r
+\r
+void *_malloc(size_t bytes, void *owner)\r
+{\r
+       size_t  closestMatch = 0;\r
+       void    *bestMatchAddr = 0;\r
+\r
        // Initialise Heap\r
        if(_heap_start == NULL)\r
-       {LOCAL void     *sbrk(int delta);\r
+       {\r
                _heap_start = sbrk(0);\r
                _heap_end = _heap_start;\r
                extendHeap(HEAP_INIT_SIZE);\r
        }\r
+\r
+       // Zero bytes, return a random area (in .rodata)\r
+       if( bytes == 0 )\r
+               return (void*)_heap_zero_allocation.data;       \r
+\r
+       // Calculate the required block size\r
+       size_t bestSize = CALC_BLOCK_SIZE(bytes);\r
        \r
-       curBlock = _heap_start;\r
-       \r
-       bestSize = bytes + sizeof(heap_head) + sizeof(heap_foot) + BLOCK_SIZE - 1;\r
-       bestSize = (bestSize/BLOCK_SIZE)*BLOCK_SIZE;    //Round up to block size\r
-       \r
-       while((Uint)curBlock < (Uint)_heap_end)\r
+       heap_head       *curBlock;\r
+       for(curBlock = _heap_start; curBlock < _heap_end; curBlock = NEXT_HEAD(curBlock))\r
        {\r
-               //SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic);\r
+               //_SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic);\r
                if(curBlock->magic == MAGIC_FREE)\r
                {\r
+                       // Perfect match, nice\r
                        if(curBlock->size == bestSize)\r
                                break;\r
+                       // Check if this is a tighter match than the last free block\r
                        if(bestSize < curBlock->size && (curBlock->size < closestMatch || closestMatch == 0)) {\r
                                closestMatch = curBlock->size;\r
-                               bestMatchAddr = (Uint)curBlock;\r
+                               bestMatchAddr = curBlock;\r
                        }\r
                }\r
                else if(curBlock->magic != MAGIC)\r
                {\r
                        //Corrupt Heap\r
-                       //SysDebug("malloc: Corrupt Heap\n");\r
+                       Heap_Validate(1);\r
+                       _SysDebug("malloc: Corrupt Heap when called by %p\n", owner);\r
+                       exit(128);\r
                        return NULL;\r
                }\r
-               curBlock = (heap_head*)((Uint)curBlock + curBlock->size);\r
        }\r
        \r
-       if((Uint)curBlock < (Uint)_heap_start) {\r
-               //SysDebug("malloc: Heap underrun for some reason\n");\r
+       if(curBlock < _heap_start) {\r
+               Heap_Validate(1);\r
+               _SysDebug("malloc: Heap underrun for some reason\n");\r
+               exit(128);\r
                return NULL;\r
        }\r
        \r
        //Found a perfect match\r
-       if((Uint)curBlock < (Uint)_heap_end) {\r
+       if(curBlock < _heap_end) {\r
                curBlock->magic = MAGIC;\r
-               return (void*)((Uint)curBlock + sizeof(heap_head));\r
+               curBlock->RealSize = bytes;\r
+               curBlock->Caller = owner;\r
+               return curBlock->data;\r
        }\r
        \r
        //Out of Heap Space\r
        if(!closestMatch) {\r
                curBlock = extendHeap(bestSize);        //Allocate more\r
                if(curBlock == NULL) {\r
-                       //SysDebug("malloc: Out of Heap Space\n");\r
+                       _SysDebug("malloc: Out of Heap Space\n");\r
                        return NULL;\r
                }\r
                curBlock->magic = MAGIC;\r
-               return (void*)((Uint)curBlock + sizeof(heap_head));\r
+               curBlock->RealSize = bytes;\r
+               curBlock->Caller = owner;\r
+               DEBUGS("malloc(0x%x) = %p (extend) 0x%x", bytes, curBlock->data, bestSize);\r
+               return curBlock->data;\r
        }\r
        \r
-       //Split Block?\r
+       heap_head *besthead = (void*)bestMatchAddr;\r
+       \r
+       // Do we need to split this block?\r
        if(closestMatch - bestSize > BLOCK_SIZE) {\r
                heap_foot       *foot;\r
+               \r
+               // Block we're going to return\r
                curBlock = (heap_head*)bestMatchAddr;\r
                curBlock->magic = MAGIC;\r
                curBlock->size = bestSize;\r
-               foot = (heap_foot*)(bestMatchAddr + bestSize - sizeof(heap_foot));\r
+               foot = THIS_FOOT(curBlock);\r
                foot->header = curBlock;\r
                foot->magic = MAGIC;\r
 \r
+               // Remaining parts of the block\r
                curBlock = (heap_head*)(bestMatchAddr + bestSize);\r
                curBlock->magic = MAGIC_FREE;\r
                curBlock->size = closestMatch - bestSize;\r
-               \r
-               foot = (heap_foot*)(bestMatchAddr + closestMatch - sizeof(heap_foot));\r
+               foot = THIS_FOOT(curBlock);\r
                foot->header = curBlock;\r
-               \r
-               ((heap_head*)bestMatchAddr)->magic = MAGIC;     //mark as used\r
-               return (void*)(bestMatchAddr + sizeof(heap_head));\r
+       \r
+               // Mark return as used  \r
+               DEBUGS("malloc(0x%x) = %p (split) 0x%x", bytes, besthead->data, bestSize);\r
+       }\r
+       else {\r
+               // No need to split\r
+               DEBUGS("malloc(0x%x) = %p (reuse) 0x%x", bytes, besthead->data, besthead->size);\r
        }\r
        \r
-       //Don't Split the block\r
-       ((heap_head*)bestMatchAddr)->magic = MAGIC;\r
-       return (void*)(bestMatchAddr+sizeof(heap_head));\r
+       besthead->magic = MAGIC;\r
+       besthead->RealSize = bytes;\r
+       besthead->Caller = owner;\r
+       return besthead->data;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT void *calloc(size_t bytes, size_t count)\r
+ * \brief Allocate and zero a block of memory\r
+ * \param __nmemb      Number of memeber elements\r
+ * \param __size       Size of one element\r
+ */\r
+EXPORT void *calloc(size_t __nmemb, size_t __size)\r
+{\r
+       void    *ret = _malloc(__size*__nmemb, __builtin_return_address(0));\r
+       if(!ret)        return NULL;\r
+       memset(ret, 0, __size*__nmemb);\r
+       return ret;\r
 }\r
 \r
 /**\r
@@ -140,35 +225,73 @@ EXPORT void *malloc(size_t bytes)
 */\r
 EXPORT void free(void *mem)\r
 {\r
-       heap_head       *head = mem;\r
-       \r
-       if(head->magic != MAGIC)        //Valid Heap Address\r
-               return;\r
+       if( !_libc_free(mem) ) {\r
+               Heap_Validate(1);\r
+               exit(0);\r
+       }\r
+}\r
+\r
+// Exported for libc++\r
+EXPORT bool _libc_free(void *mem)\r
+{\r
+       heap_head       *head = (heap_head*)mem - 1;\r
+\r
+       // Free of NULL or the zero allocation does nothing\r
+       if(!mem || mem == _heap_zero_allocation.data)\r
+               return true;\r
+       \r
+       // Sanity check the head address\r
+       if(head->magic != MAGIC) {\r
+               if( head->magic != MAGIC_FREE ) {\r
+                       _SysDebug("Double free of %p by %p", mem, __builtin_return_address(0));\r
+               }\r
+               else {\r
+                       _SysDebug("Free of invalid pointer %p by ", mem, __builtin_return_address(0));\r
+               }\r
+               return false;\r
+       }\r
        \r
        head->magic = MAGIC_FREE;\r
+       DEBUGS("free(%p) : 0x%x bytes", mem, head->size);\r
        \r
-       //Unify Right\r
-       if((Uint)head + head->size < (Uint)_heap_end)\r
+       // Unify Right\r
+       if( NEXT_HEAD(head) < _heap_end )\r
        {\r
-               heap_head       *nextHead = (heap_head*)((Uint)head + head->size);\r
-               if(nextHead->magic == MAGIC_FREE) {     //Is the next block free\r
-                       head->size += nextHead->size;   //Amalgamate\r
+               heap_head       *nextHead = NEXT_HEAD(head);\r
+               // Is the next block free?\r
+               if(nextHead->magic == MAGIC_FREE)\r
+               {\r
+                       head->size += nextHead->size;   // Amalgamate\r
+                       THIS_FOOT(head)->header = head;\r
                        nextHead->magic = 0;    //For Security\r
                }\r
        }\r
-       //Unify Left\r
-       if((Uint)head - sizeof(heap_foot) > (Uint)_heap_start)\r
+       \r
+       // Unify Left\r
+       if( head > _heap_start )\r
        {\r
-               heap_head       *prevHead;\r
-               heap_foot       *prevFoot = (heap_foot *)((Uint)head - sizeof(heap_foot));\r
-               if(prevFoot->magic == MAGIC) {\r
-                       prevHead = prevFoot->header;\r
-                       if(prevHead->magic == MAGIC_FREE) {\r
-                               prevHead->size += head->size;   //Amalgamate\r
-                               head->magic = 0;        //For Security\r
-                       }\r
+               heap_foot *prevFoot = PREV_FOOT(head);\r
+               if( prevFoot->magic != MAGIC )\r
+               {\r
+                       _SysDebug("Heap corruption, previous foot magic invalid");\r
+                       Heap_Validate(1);\r
+                       return false;\r
+               }\r
+               \r
+               heap_head *prevHead = prevFoot->header;\r
+               if(prevHead->magic == MAGIC_FREE)\r
+               {\r
+                       // Amalgamate\r
+                       prevHead->size += head->size;\r
+                       THIS_FOOT(prevHead)->header = prevHead;\r
+                       // For Security\r
+                       head->magic = 0;\r
+                       prevFoot->magic = 0;\r
+                       prevFoot->header = NULL;\r
                }\r
        }\r
+       \r
+       return true;\r
 }\r
 \r
 /**\r
@@ -180,38 +303,69 @@ EXPORT void free(void *mem)
 */\r
 EXPORT void *realloc(void *oldPos, size_t bytes)\r
 {\r
-       void *ret;\r
-       heap_head       *head;\r
-       \r
-       if(oldPos == NULL) {\r
-               return malloc(bytes);\r
+       if(oldPos == NULL || oldPos == _heap_zero_allocation.data) {\r
+               return _malloc(bytes, __builtin_return_address(0));\r
+       }\r
+\r
+       size_t  reqd_size = CALC_BLOCK_SIZE(bytes);     \r
+\r
+       // Check for free space within the block\r
+       // - oldPos points to just after the header, so -1 gives the header\r
+       heap_head *head = (heap_head*)oldPos - 1;\r
+       if( head->size >= reqd_size ) {\r
+               head->RealSize = bytes;\r
+               return oldPos;\r
        }\r
        \r
-       //Check for free space after block\r
-       head = (heap_head*)((Uint)oldPos-sizeof(heap_head));\r
+       // Check for free space after the block\r
+       heap_head *nexthead = NEXT_HEAD(head);\r
+       assert( nexthead <= _heap_end );\r
+       if( nexthead != _heap_end && nexthead->magic == MAGIC_FREE && head->size + nexthead->size >= reqd_size )\r
+       {\r
+               // Split next block\r
+               if( head->size + nexthead->size > reqd_size )\r
+               {\r
+                       size_t newblocksize = nexthead->size - (reqd_size - head->size);\r
+                       head->size = reqd_size;\r
+                       \r
+                       nexthead = NEXT_HEAD(head);\r
+                       nexthead->size = newblocksize;\r
+                       nexthead->magic = MAGIC_FREE;\r
+                       THIS_FOOT(nexthead)->header = nexthead;\r
+               }\r
+               else\r
+               {\r
+                       head->size = reqd_size;\r
+               }\r
+               THIS_FOOT(head)->magic = MAGIC;\r
+               THIS_FOOT(head)->header = head;\r
+               head->RealSize = bytes;\r
+               return oldPos;\r
+       }\r
        \r
-       //Hack to used free's amagamating algorithym and malloc's splitting\r
-       free(oldPos);\r
+       // TODO: Should I check for free before too? What about before AND after?\r
        \r
-       //Allocate new memory\r
-       ret = malloc(bytes);\r
+       // Allocate new memory\r
+       void *ret = _malloc(bytes, __builtin_return_address(0));\r
        if(ret == NULL)\r
                return NULL;\r
+       heap_head *newhead = (heap_head*)ret - 1;\r
        \r
-       //Copy Old Data\r
-       if((Uint)ret != (Uint)oldPos) {\r
-               memcpy(ret, oldPos, head->size-sizeof(heap_head)-sizeof(heap_foot));\r
-       }\r
+       // Copy Old Data\r
+       assert( head->size < newhead->size );\r
+       size_t copy_size = head->size-sizeof(heap_head)-sizeof(heap_foot);\r
+       memcpy(ret, oldPos, copy_size);\r
+       free(oldPos);\r
        \r
        //Return\r
        return ret;\r
 }\r
 \r
 /**\r
- \fn LOCAL void *extendHeap(int bytes)\r
- \brief Create a new block at the end of the heap area\r
\param bytes  Integer - Size reqired\r
- \return Pointer to last free block\r
\fn LOCAL void *extendHeap(int bytes)\r
\brief Create a new block at the end of the heap area\r
* \param bytes        Integer - Size reqired\r
\return Pointer to last free block\r
  */\r
 \r
 LOCAL void *extendHeap(int bytes)\r
@@ -224,19 +378,18 @@ LOCAL void *extendHeap(int bytes)
        if(foot == (void*)-1)\r
                return NULL;\r
        \r
-       \r
        //Create New Block\r
        // Header\r
        head->magic = MAGIC_FREE;       //Unallocated\r
        head->size = bytes;\r
        // Footer\r
-       foot = _heap_end + bytes - sizeof(heap_foot);\r
+       foot = THIS_FOOT(head);\r
        foot->header = head;\r
        foot->magic = MAGIC;\r
        \r
        //Combine with previous block if nessasary\r
-       if(_heap_end != _heap_start && ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->magic == MAGIC) {\r
-               heap_head       *tmpHead = ((heap_foot*)((Uint)_heap_end-sizeof(heap_foot)))->header;\r
+       if(_heap_end != _heap_start && ((heap_foot*)((uintptr_t)_heap_end-sizeof(heap_foot)))->magic == MAGIC) {\r
+               heap_head       *tmpHead = ((heap_foot*)((uintptr_t)_heap_end-sizeof(heap_foot)))->header;\r
                if(tmpHead->magic == MAGIC_FREE) {\r
                        tmpHead->size += bytes;\r
                        foot->header = tmpHead;\r
@@ -244,7 +397,7 @@ LOCAL void *extendHeap(int bytes)
                }\r
        }\r
        \r
-       _heap_end = (void*) ((Uint)foot+sizeof(heap_foot));\r
+       _heap_end = (void*) ((uintptr_t)foot+sizeof(heap_foot));\r
        return head;\r
 }\r
 \r
@@ -256,24 +409,52 @@ LOCAL void *extendHeap(int bytes)
 */\r
 EXPORT void *sbrk(int increment)\r
 {\r
-       size_t newEnd;\r
-       static size_t oldEnd = 0;\r
-       static size_t curEnd = 0;\r
+       static uintptr_t oldEnd = 0;\r
+       static uintptr_t curEnd = 0;\r
 \r
-       //SysDebug("sbrk: (increment=%i)\n", increment);\r
+       //_SysDebug("sbrk: (increment=%i)", increment);\r
 \r
-       if (oldEnd == 0)        curEnd = oldEnd = brk(0);\r
+       if (curEnd == 0) {\r
+               oldEnd = curEnd = (uintptr_t)FindHeapBase();\r
+               //_SysAllocate(curEnd); // Allocate the first page\r
+       }\r
 \r
-       //SysDebug(" sbrk: oldEnd = 0x%x\n", oldEnd);\r
+       //_SysDebug(" sbrk: oldEnd = 0x%x", oldEnd);\r
        if (increment == 0)     return (void *) curEnd;\r
 \r
-       newEnd = curEnd + increment;\r
-\r
-       if (brk(newEnd) == curEnd)      return (void *) -1;\r
        oldEnd = curEnd;\r
-       curEnd = newEnd;\r
-       //SysDebug(" sbrk: newEnd = 0x%x\n", newEnd);\r
 \r
+       // Single Page\r
+       if( (curEnd & 0xFFF) && (curEnd & 0xFFF) + increment < 0x1000 )\r
+       {\r
+               //if( curEnd & 0xFFF == 0 )\r
+               //{\r
+               //      if( !_SysAllocate(curEnd) )\r
+               //      {\r
+               //              _SysDebug("sbrk - Error allocating memory");\r
+               //              return (void*)-1;\r
+               //      }\r
+               //}\r
+               curEnd += increment;\r
+               //_SysDebug("sbrk: RETURN %p (single page, no alloc)", (void *) oldEnd);\r
+               return (void *)oldEnd;\r
+       }\r
+\r
+       increment -= curEnd & 0xFFF;\r
+       curEnd += 0xFFF;        curEnd &= ~0xFFF;\r
+       while( increment > 0 )\r
+       {\r
+               if( !_SysAllocate(curEnd) )\r
+               {\r
+                       // Error?\r
+                       _SysDebug("sbrk - Error allocating memory");\r
+                       return (void*)-1;\r
+               }\r
+               increment -= 0x1000;\r
+               curEnd += 0x1000;\r
+       }\r
+\r
+       //_SysDebug("sbrk: RETURN %p", (void *) oldEnd);\r
        return (void *) oldEnd;\r
 }\r
 \r
@@ -282,12 +463,14 @@ EXPORT void *sbrk(int increment)
  */\r
 EXPORT int IsHeap(void *ptr)\r
 {\r
+       if( ptr == _heap_zero_allocation.data )\r
+               return 1;\r
        #if 0\r
        heap_head       *head;\r
        heap_foot       *foot;\r
        #endif\r
-       if( (Uint)ptr < (Uint)_heap_start )     return 0;\r
-       if( (Uint)ptr > (Uint)_heap_end )       return 0;\r
+       if( (uintptr_t)ptr < (uintptr_t)_heap_start )   return 0;\r
+       if( (uintptr_t)ptr > (uintptr_t)_heap_end )     return 0;\r
        \r
        #if 0\r
        head = (void*)((Uint)ptr - 4);\r
@@ -304,10 +487,12 @@ EXPORT int IsHeap(void *ptr)
  */\r
 static void *FindHeapBase()\r
 {\r
+       #if 0\r
        #define MAX             0xC0000000      // Address\r
        #define THRESHOLD       512     // Pages\r
        uint    addr;\r
        uint    stretch = 0;\r
+       uint64_t        tmp;\r
        \r
        // Scan address space\r
        for(addr = 0;\r
@@ -315,33 +500,46 @@ static void *FindHeapBase()
                addr += 0x1000\r
                )\r
        {\r
-               if( _SysGetPhys(addr) == 0 ) {\r
+               tmp = _SysGetPhys(addr);\r
+               if( tmp != 0 ) {\r
                        stretch = 0;\r
                } else {\r
                        stretch ++;\r
                        if(stretch > THRESHOLD)\r
                        {\r
-                               return (void*)( addr + stretch*0x1000 );\r
+                               return (void*)( addr - stretch*0x1000 );\r
                        }\r
                }\r
+               //__asm__ __volatile__ (\r
+               //      "push %%ebx;mov %%edx,%%ebx;int $0xAC;pop %%ebx"\r
+               //      ::"a"(256),"d"("%x"),"c"(addr));\r
        }\r
+       \r
        return NULL;\r
+       #else\r
+       return (void*)0x00900000;\r
+       #endif\r
 }\r
 \r
-LOCAL uint brk(int delta)\r
+LOCAL uint brk(uintptr_t newpos)\r
 {\r
-       static uint     curpos;\r
+       static uintptr_t        curpos;\r
        uint    pages;\r
        uint    ret = curpos;\r
+        int    delta;\r
+       \r
+       _SysDebug("brk: (newpos=0x%x)", newpos);\r
        \r
        // Find initial position\r
-       if(curpos == 0) curpos = (uint)FindHeapBase();\r
+       if(curpos == 0) curpos = (uintptr_t)FindHeapBase();\r
        \r
        // Get Current Position\r
-       if(delta == 0)\r
-       {\r
-               return curpos;\r
-       }\r
+       if(newpos == 0) return curpos;\r
+       \r
+       if(newpos < curpos)     return newpos;\r
+       \r
+       delta = newpos - curpos;\r
+       _SysDebug(" brk: delta = 0x%x", delta);\r
        \r
        // Do we need to add pages\r
        if(curpos & 0xFFF && (curpos & 0xFFF) + delta < 0x1000)\r
@@ -365,3 +563,55 @@ LOCAL uint brk(int delta)
        \r
        return ret;     // Return old curpos\r
 }\r
+\r
+int Heap_Validate(int bDump)\r
+{\r
+        int    rv = 0;\r
+       heap_head *cur = _heap_start;\r
+       while( cur < (heap_head*)_heap_end && rv == 0 )\r
+       {\r
+               if( cur->magic == MAGIC ) {\r
+                       if( bDump ) {\r
+                               _SysDebug("Used block %p[0x%x] - ptr=%p,Owner=%p,Size=0x%x",\r
+                                       cur, cur->size, cur->data,\r
+                                       cur->Caller, cur->RealSize\r
+                                       );\r
+                       }\r
+               }\r
+               else if( cur->magic == MAGIC_FREE ) {\r
+                       if( bDump ) {\r
+                               _SysDebug("Free block %p[0x%x]", cur, cur->size, cur->data);\r
+                       }\r
+               }\r
+               else {\r
+                       _SysDebug("Block %p bad magic (0x%x)", cur, cur->magic);\r
+                       rv = 1;\r
+                       break ;\r
+               }\r
+               heap_foot *foot = THIS_FOOT(cur);\r
+               if( foot->magic != MAGIC ) {\r
+                       _SysDebug("- %p: Foot magic clobbered (0x%x!=0x%x)", cur, foot->magic, MAGIC);\r
+                       rv = 1;\r
+               }\r
+               if( foot->header != cur ) {\r
+                       _SysDebug("- %p: Head pointer clobbered (%p)", cur, foot->header);\r
+                       rv = 1;\r
+               }\r
+       \r
+               if( rv && !bDump ) {\r
+                       _SysDebug("%s block %p[0x%x] - ptr=%p,Owner=%p,Size=0x%x",\r
+                               (cur->magic == MAGIC ? "Used":"Free"),\r
+                               cur, cur->size, cur->data,\r
+                               cur->Caller, cur->RealSize\r
+                               );\r
+               }       \r
+       \r
+               cur = NEXT_HEAD(cur);\r
+       }\r
+       if( rv && !bDump ) {\r
+               _SysDebug("- Caller: %p", __builtin_return_address(0));\r
+               exit(1);\r
+       }\r
+       return 0;\r
+}\r
+\r

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