Usermode/libc - Minor fix to memmove
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / heap.c
index 23df92a..9b6799b 100644 (file)
@@ -4,8 +4,15 @@ heap.c - Heap Manager
 */\r
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
+#include <string.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
@@ -14,27 +21,31 @@ heap.c - Heap Manager
 \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
+       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
+// === LOCAL VARIABLES ===\r
+static void    *_heap_start = NULL;\r
+static void    *_heap_end = NULL;\r
 \r
-//Prototypes\r
-EXPORT void    *malloc(Uint bytes);\r
+// === PROTOTYPES ===\r
+EXPORT void    *malloc(size_t bytes);\r
+EXPORT void    *calloc(size_t bytes, size_t count);\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
+LOCAL void     Heap_Dump(void);\r
 \r
 //Code\r
 \r
@@ -46,67 +57,76 @@ 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
+       size_t  bestSize;\r
+       size_t  closestMatch = 0;\r
+       void    *bestMatchAddr = 0;\r
        heap_head       *curBlock;\r
-       \r
+\r
+//     _SysDebug("&_heap_start = %p, _heap_start = %p", &_heap_start, _heap_start);\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
        curBlock = _heap_start;\r
+//     _SysDebug("_heap_start = %p", _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
+       while( (uintptr_t)curBlock < (uintptr_t)_heap_end)\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
                        if(curBlock->size == bestSize)\r
                                break;\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_Dump();\r
+                       _SysDebug("malloc: Corrupt Heap\n");\r
+                       exit(128);\r
                        return NULL;\r
                }\r
-               curBlock = (heap_head*)((Uint)curBlock + curBlock->size);\r
+               curBlock = (heap_head*)((uintptr_t)curBlock + curBlock->size);\r
        }\r
        \r
-       if((Uint)curBlock < (Uint)_heap_start) {\r
-               //SysDebug("malloc: Heap underrun for some reason\n");\r
+       if((uintptr_t)curBlock < (uintptr_t)_heap_start) {\r
+               Heap_Dump();\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((uintptr_t)curBlock < (uintptr_t)_heap_end) {\r
                curBlock->magic = MAGIC;\r
-               return (void*)((Uint)curBlock + sizeof(heap_head));\r
+               return (void*)((uintptr_t)curBlock + sizeof(heap_head));\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
+               DEBUGS("malloc(0x%x) = %p (extend) 0x%x", bytes, curBlock->data, bestSize);\r
+               return curBlock->data;\r
        }\r
        \r
+       heap_head *besthead = (void*)bestMatchAddr;\r
+       \r
        //Split Block?\r
        if(closestMatch - bestSize > BLOCK_SIZE) {\r
                heap_foot       *foot;\r
@@ -124,13 +144,29 @@ EXPORT void *malloc(size_t bytes)
                foot = (heap_foot*)(bestMatchAddr + closestMatch - sizeof(heap_foot));\r
                foot->header = curBlock;\r
                \r
-               ((heap_head*)bestMatchAddr)->magic = MAGIC;     //mark as used\r
-               return (void*)(bestMatchAddr + sizeof(heap_head));\r
+               besthead->magic = MAGIC;        //mark as used\r
+               DEBUGS("malloc(0x%x) = %p (split) 0x%x", bytes, besthead->data, bestSize);\r
+               return besthead->data;\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
+       DEBUGS("malloc(0x%x) = %p (reuse) 0x%x", bytes, besthead->data, besthead->size);\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);\r
+       if(!ret)        return NULL;\r
+       memset(ret, 0, __size*__nmemb);\r
+       return ret;\r
 }\r
 \r
 /**\r
@@ -140,27 +176,31 @@ EXPORT void *malloc(size_t bytes)
 */\r
 EXPORT void free(void *mem)\r
 {\r
-       heap_head       *head = mem;\r
+       heap_head       *head = (void*)((intptr_t)mem-sizeof(heap_head));\r
+\r
+       // Sanity please!\r
+       if(!mem)        return;\r
        \r
        if(head->magic != MAGIC)        //Valid Heap Address\r
                return;\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
+       if((uintptr_t)head + head->size < (uintptr_t)_heap_end)\r
        {\r
-               heap_head       *nextHead = (heap_head*)((Uint)head + head->size);\r
+               heap_head       *nextHead = (heap_head*)((intptr_t)head + head->size);\r
                if(nextHead->magic == MAGIC_FREE) {     //Is the next block free\r
                        head->size += nextHead->size;   //Amalgamate\r
                        nextHead->magic = 0;    //For Security\r
                }\r
        }\r
        //Unify Left\r
-       if((Uint)head - sizeof(heap_foot) > (Uint)_heap_start)\r
+       if((uintptr_t)head - sizeof(heap_foot) > (uintptr_t)_heap_start)\r
        {\r
                heap_head       *prevHead;\r
-               heap_foot       *prevFoot = (heap_foot *)((Uint)head - sizeof(heap_foot));\r
+               heap_foot       *prevFoot = (heap_foot *)((intptr_t)head - sizeof(heap_foot));\r
                if(prevFoot->magic == MAGIC) {\r
                        prevHead = prevFoot->header;\r
                        if(prevHead->magic == MAGIC_FREE) {\r
@@ -188,7 +228,7 @@ EXPORT void *realloc(void *oldPos, size_t bytes)
        }\r
        \r
        //Check for free space after block\r
-       head = (heap_head*)((Uint)oldPos-sizeof(heap_head));\r
+       head = (heap_head*)((uintptr_t)oldPos-sizeof(heap_head));\r
        \r
        //Hack to used free's amagamating algorithym and malloc's splitting\r
        free(oldPos);\r
@@ -199,7 +239,7 @@ EXPORT void *realloc(void *oldPos, size_t bytes)
                return NULL;\r
        \r
        //Copy Old Data\r
-       if((Uint)ret != (Uint)oldPos) {\r
+       if(ret != oldPos) {\r
                memcpy(ret, oldPos, head->size-sizeof(heap_head)-sizeof(heap_foot));\r
        }\r
        \r
@@ -208,10 +248,10 @@ EXPORT void *realloc(void *oldPos, size_t bytes)
 }\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,7 +264,6 @@ 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
@@ -235,8 +274,8 @@ LOCAL void *extendHeap(int bytes)
        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 +283,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 +295,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
@@ -286,8 +353,8 @@ EXPORT int IsHeap(void *ptr)
        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 +371,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 +384,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 +447,23 @@ LOCAL uint brk(int delta)
        \r
        return ret;     // Return old curpos\r
 }\r
+\r
+void Heap_Dump(void)\r
+{\r
+       heap_head *cur = _heap_start;\r
+       while( cur < (heap_head*)_heap_end )\r
+       {\r
+               if( cur->magic == MAGIC ) {\r
+                       _SysDebug("Used block %p[0x%x] - ptr=%p", cur, cur->size, cur->data);\r
+               }\r
+               else if( cur->magic == MAGIC_FREE ) {\r
+                       _SysDebug("Free block %p[0x%x] - ptr=%p", cur, cur->size, cur->data);\r
+               }\r
+               else {\r
+                       _SysDebug("Block %p bad magic (0x%x)", cur, cur->magic);\r
+                       break ;\r
+               }\r
+               cur = (void*)( (char*)cur + cur->size );\r
+       }\r
+}\r
+\r

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