]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - zone.c
do not use non-standard strnlen function
[xonotic/darkplaces.git] / zone.c
diff --git a/zone.c b/zone.c
index 17e788abe2a02212a55348c61baaa8daf040a8f9..47c870e5929d79bed3bcafe28e052ef54c56d649 100644 (file)
--- a/zone.c
+++ b/zone.c
@@ -35,6 +35,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define MEMHEADER_SENTINEL_FOR_ADDRESS(p) ((sentinel_seed ^ (unsigned int) (uintptr_t) (p)) + sentinel_seed)
 unsigned int sentinel_seed;
 
+qboolean mem_bigendian = false;
+
 // LordHavoc: enables our own low-level allocator (instead of malloc)
 #define MEMCLUMPING 0
 #define MEMCLUMPING_FREECLUMPS 0
@@ -43,7 +45,7 @@ unsigned int sentinel_seed;
 // smallest unit we care about is this many bytes
 #define MEMUNIT 128
 // try to do 32MB clumps, but overhead eats into this
-#define MEMWANTCLUMPSIZE (1<<29)
+#define MEMWANTCLUMPSIZE (1<<27)
 // give malloc padding so we can't waste most of a page at the end
 #define MEMCLUMPSIZE (MEMWANTCLUMPSIZE - MEMWANTCLUMPSIZE/MEMUNIT/32 - 128)
 #define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
@@ -82,6 +84,9 @@ cvar_t developer_memorydebug = {0, "developer_memorydebug", "0", "enables memory
 
 static mempool_t *poolchain = NULL;
 
+void Mem_PrintStats(void);
+void Mem_PrintList(size_t minallocationsize);
+
 #if MEMCLUMPING != 2
 // some platforms have a malloc that returns NULL but succeeds later
 // (Windows growing its swapfile for example)
@@ -95,11 +100,7 @@ static void *attempt_malloc(size_t size)
                base = (void *)malloc(size);
                if (base)
                        return base;
-#ifdef WIN32
-               Sleep(1);
-#else
-               usleep(1000);
-#endif
+               Sys_Sleep(1000);
        }
        return NULL;
 }
@@ -307,14 +308,23 @@ static void Clump_FreeBlock(void *base, size_t size)
 #endif
 }
 
-void *_Mem_Alloc(mempool_t *pool, size_t size, const char *filename, int fileline)
+void *_Mem_Alloc(mempool_t *pool, void *olddata, size_t size, size_t alignment, const char *filename, int fileline)
 {
        unsigned int sentinel1;
        unsigned int sentinel2;
        size_t realsize;
+       size_t sharedsize;
+       size_t remainsize;
        memheader_t *mem;
+       memheader_t *oldmem;
+       unsigned char *base;
+
        if (size <= 0)
+       {
+               if (olddata)
+                       _Mem_Free(olddata, filename, fileline);
                return NULL;
+       }
        if (pool == NULL)
                Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
        if (developer.integer && developer_memory.integer)
@@ -322,11 +332,20 @@ void *_Mem_Alloc(mempool_t *pool, size_t size, const char *filename, int filelin
        //if (developer.integer && developer_memorydebug.integer)
        //      _Mem_CheckSentinelsGlobal(filename, fileline);
        pool->totalsize += size;
-       realsize = sizeof(memheader_t) + size + sizeof(sentinel2);
+       realsize = alignment + sizeof(memheader_t) + size + sizeof(sentinel2);
        pool->realsize += realsize;
-       mem = (memheader_t *)Clump_AllocBlock(realsize);
-       if (mem == NULL)
+       base = (unsigned char *)Clump_AllocBlock(realsize);
+       if (base== NULL)
+       {
+               Mem_PrintList(0);
+               Mem_PrintStats();
+               Mem_PrintList(1<<30);
+               Mem_PrintStats();
                Sys_Error("Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline);
+       }
+       // calculate address that aligns the end of the memheader_t to the specified alignment
+       mem = (memheader_t*)((((size_t)base + sizeof(memheader_t) + (alignment-1)) & ~(alignment-1)) - sizeof(memheader_t));
+       mem->baseaddress = (void*)base;
        mem->filename = filename;
        mem->fileline = fileline;
        mem->size = size;
@@ -344,7 +363,19 @@ void *_Mem_Alloc(mempool_t *pool, size_t size, const char *filename, int filelin
        pool->chain = mem;
        if (mem->next)
                mem->next->prev = mem;
-       memset((void *)((unsigned char *) mem + sizeof(memheader_t)), 0, mem->size);
+
+       // copy the shared portion in the case of a realloc, then memset the rest
+       sharedsize = 0;
+       remainsize = size;
+       if (olddata)
+       {
+               oldmem = (memheader_t*)olddata - 1;
+               sharedsize = min(oldmem->size, size);
+               memcpy((void *)((unsigned char *) mem + sizeof(memheader_t)), olddata, sharedsize);
+               remainsize -= sharedsize;
+               _Mem_Free(olddata, filename, fileline);
+       }
+       memset((void *)((unsigned char *) mem + sizeof(memheader_t) + sharedsize), 0, remainsize);
        return (void *)((unsigned char *) mem + sizeof(memheader_t));
 }
 
@@ -382,7 +413,7 @@ static void _Mem_FreeBlock(memheader_t *mem, const char *filename, int fileline)
        realsize = sizeof(memheader_t) + size + sizeof(sentinel2);
        pool->totalsize -= size;
        pool->realsize -= realsize;
-       Clump_FreeBlock(mem, realsize);
+       Clump_FreeBlock(mem->baseaddress, realsize);
 }
 
 void _Mem_Free(void *data, const char *filename, int fileline)
@@ -410,7 +441,13 @@ mempool_t *_Mem_AllocPool(const char *name, int flags, mempool_t *parent, const
        //      _Mem_CheckSentinelsGlobal(filename, fileline);
        pool = (mempool_t *)Clump_AllocBlock(sizeof(mempool_t));
        if (pool == NULL)
+       {
+               Mem_PrintList(0);
+               Mem_PrintStats();
+               Mem_PrintList(1<<30);
+               Mem_PrintStats();
                Sys_Error("Mem_AllocPool: out of memory (allocpool at %s:%i)", filename, fileline);
+       }
        memset(pool, 0, sizeof(mempool_t));
        pool->sentinel1 = MEMHEADER_SENTINEL_FOR_ADDRESS(&pool->sentinel1);
        pool->sentinel2 = MEMHEADER_SENTINEL_FOR_ADDRESS(&pool->sentinel2);
@@ -780,6 +817,10 @@ Memory_Init
 */
 void Memory_Init (void)
 {
+       static union {unsigned short s;unsigned char b[2];} u;
+       u.s = 0x100;
+       mem_bigendian = u.b[0];
+
        sentinel_seed = rand();
        poolchain = NULL;
        tempmempool = Mem_AllocPool("Temporary Memory", POOLFLAG_TEMP, NULL);