static void _Mem_CheckPoolIntegrity (memPool_t *pool, const char *fileName, const int fileLine) { memBlock_t *mem; uint32_t blocks; uint32_t size; int j = 0; assert(pool); if (!pool) return; /* Check sentinels */ for (j = 0, blocks = 0, size = 0; j < MEM_HASH; j++) { for (mem = pool->blocks[j]; mem; blocks++, mem = mem->next) { size += Mem_BlockRawSize(mem); _Mem_CheckSentinels(mem, fileName, fileLine); } } /* Check block/byte counts */ if (pool->blockCount != blocks) Sys_Error("Mem_CheckPoolIntegrity: bad block count\n" "check: %s:#%i", fileName, fileLine); if (pool->byteCount != size) Sys_Error("Mem_CheckPoolIntegrity: bad pool size\n" "check: %s:#%i", fileName, fileLine); }
void *_Mem_ReAlloc (void *ptr, size_t size, const char *fileName, const int fileLine) { memPool_t *pool; void *newPtr; if (!size) Sys_Error("Use Mem_Free instead"); if (!ptr) Sys_Error("Use Mem_Alloc instead"); memBlock_t* const mem = Mem_PtrToBlock(ptr); _Mem_CheckSentinels(mem, fileName, fileLine); /* if size matches, do nothing */ if (mem->memSize == size) return ptr; pool = mem->pool; /* allocate memory for the new size */ newPtr = _Mem_Alloc(size, false, pool, mem->tagNum, fileName, fileLine); /* copy old data */ memcpy(newPtr, ptr, std::min(mem->memSize, size)); if (mem->memSize < size) { const size_t delta = size - mem->memSize; memset((byte*)newPtr + mem->memSize, 0, delta); } /* if there was old data, free it */ _Mem_Free(ptr, fileName, fileLine); _Mem_CheckSentinels(Mem_PtrToBlock(newPtr), fileName, fileLine); return newPtr; }
static void _Mem_CheckSentinelsPool( mempool_t *pool, const char *filename, int fileline ) { memheader_t *mem; mempool_t *child; // recurse into children if( pool->child ) { for( child = pool->child; child; child = child->next ) _Mem_CheckSentinelsPool( child, filename, fileline ); } assert( pool->sentinel1 == MEMHEADER_SENTINEL1 ); assert( pool->sentinel2 == MEMHEADER_SENTINEL1 ); if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) _Mem_Error( "_Mem_CheckSentinelsPool: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline ); if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) _Mem_Error( "_Mem_CheckSentinelsPool: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline ); for( mem = pool->chain; mem; mem = mem->next ) _Mem_CheckSentinels( (void *)( (qbyte *) mem + sizeof( memheader_t ) ), filename, fileline ); }
/** * @sa _Mem_FreePool */ void _Mem_Free (void *ptr, const char *fileName, const int fileLine) { memBlock_t *search; memBlock_t **prev; if (!ptr) return; memBlock_t* const mem = Mem_PtrToBlock(ptr); _Mem_CheckSentinels(mem, fileName, fileLine); SDL_LockMutex(z_lock); /* Decrement counters */ mem->pool->blockCount--; mem->pool->byteCount -= Mem_BlockRawSize(mem); /* De-link it */ prev = &mem->pool->blocks[(uintptr_t)mem % MEM_HASH]; for (;;) { search = *prev; if (!search) break; if (search == mem) { *prev = search->next; break; } prev = &search->next; } SDL_UnlockMutex(z_lock); /* Free it */ free(mem); }