+ // too big, allocate it directly
+#endif
+#if MEMCLUMPING == 2
+ return NULL;
+#else
+ base = (unsigned char *)attempt_malloc(size);
+ if (base && developer_memorydebug.integer)
+ memset(base, 0xAF, size);
+ return base;
+#endif
+}
+static void Clump_FreeBlock(void *base, size_t size)
+{
+#if MEMCLUMPING
+ size_t needbits;
+ size_t startbit;
+ size_t endbit;
+ size_t bit;
+ memclump_t **clumpchainpointer;
+ memclump_t *clump;
+ unsigned char *start = (unsigned char *)base;
+ for (clumpchainpointer = &clumpchain;(clump = *clumpchainpointer);clumpchainpointer = &(*clumpchainpointer)->chain)
+ {
+ if (start >= clump->block && start < clump->block + MEMCLUMPSIZE)
+ {
+ if (clump->sentinel1 != MEMHEADER_SENTINEL_FOR_ADDRESS(&clump->sentinel1))
+ Sys_Error("Clump_FreeBlock: trashed sentinel1\n");
+ if (clump->sentinel2 != MEMHEADER_SENTINEL_FOR_ADDRESS(&clump->sentinel2))
+ Sys_Error("Clump_FreeBlock: trashed sentinel2\n");
+ if (start + size > clump->block + MEMCLUMPSIZE)
+ Sys_Error("Clump_FreeBlock: block overrun\n");
+ // the block belongs to this clump, clear the range
+ needbits = (size + MEMUNIT - 1) / MEMUNIT;
+ startbit = (start - clump->block) / MEMUNIT;
+ endbit = startbit + needbits;
+ // first verify all bits are set, otherwise this may be misaligned or a double free
+ for (bit = startbit;bit < endbit;bit++)
+ if ((clump->bits[bit>>5] & (1<<(bit & 31))) == 0)
+ Sys_Error("Clump_FreeBlock: double free\n");
+ for (bit = startbit;bit < endbit;bit++)
+ clump->bits[bit>>5] &= ~(1<<(bit & 31));
+ clump->blocksinuse -= needbits;
+ memset(base, 0xFF, needbits * MEMUNIT);
+ // if all has been freed, free the clump itself
+ if (clump->blocksinuse == 0)
+ {
+ *clumpchainpointer = clump->chain;
+ if (developer_memorydebug.integer)
+ memset(clump, 0xFF, sizeof(*clump));
+#if MEMCLUMPING != 2
+ free(clump);
+#endif
+ }
+ return;
+ }
+ }
+ // does not belong to any known chunk... assume it was a direct allocation
+#endif
+#if MEMCLUMPING != 2
+ memset(base, 0xFF, size);
+ free(base);
+#endif
+}
+
+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)
+ {
+ if(olddata)
+ pool = ((memheader_t *)((unsigned char *) olddata - sizeof(memheader_t)))->pool;
+ else
+ Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
+ }
+ if (mem_mutex)
+ Thread_LockMutex(mem_mutex);
+ if (developer_memory.integer || size >= developer_memoryreportlargerthanmb.value * 1048576)
+ Con_DPrintf("Mem_Alloc: pool %s, file %s:%i, size %f bytes (%f MB)\n", pool->name, filename, fileline, (double)size, (double)size / 1048576.0f);
+ //if (developer.integer > 0 && developer_memorydebug.integer)
+ // _Mem_CheckSentinelsGlobal(filename, fileline);
+ pool->totalsize += size;
+ realsize = alignment + sizeof(memheader_t) + size + sizeof(sentinel2);
+ pool->realsize += realsize;
+ base = (unsigned char *)Clump_AllocBlock(realsize);
+ if (base == NULL)