/** * @brief Optionally returns 0 filled memory allocated in a pool with a tag */ void *_Mem_Alloc (size_t size, bool zeroFill, memPool_t *pool, const int tagNum, const char *fileName, const int fileLine) { memBlock_t *mem; /* Check pool */ if (!pool) Sys_Error("Mem_Alloc: Error - no pool given\n" "alloc: %s:#%i", fileName, fileLine); /* Check size */ if (size <= 0) Sys_Error("Mem_Alloc: Attempted allocation of '" UFO_SIZE_T "' memory ignored\n" "alloc: %s:#%i", size, fileName, fileLine); if (size > 0x40000000) Sys_Error("Mem_Alloc: Attempted allocation of '" UFO_SIZE_T "' bytes!\n" "alloc: %s:#%i", size, fileName, fileLine); /* Add header and round to cacheline */ size = (size + sizeof(memBlock_t) + sizeof(memBlockFoot_t) + 31) & ~31; mem = static_cast<memBlock_t *>(malloc(size)); if (!mem) Sys_Error("Mem_Alloc: failed on allocation of '" UFO_SIZE_T "' bytes\n" "alloc: %s:#%i", size, fileName, fileLine); /* Zero fill */ if (zeroFill) memset(mem, 0, size); /* Fill in the header */ mem->topSentinel = MEM_HEAD_SENTINEL_TOP; mem->tagNum = tagNum; mem->memSize = size - sizeof(memBlock_t) - sizeof(memBlockFoot_t); mem->pool = pool; mem->allocFile = fileName; mem->allocLine = fileLine; mem->botSentinel = MEM_HEAD_SENTINEL_BOT; /* Fill in the footer */ Mem_BlockToFooter(mem)->sentinel = MEM_FOOT_SENTINEL; SDL_LockMutex(z_lock); /* For integrity checking and stats */ pool->blockCount++; pool->byteCount += size; /* Link it in to the appropriate pool */ mem->next = pool->blocks[(uintptr_t)mem % MEM_HASH]; pool->blocks[(uintptr_t)mem % MEM_HASH] = mem; SDL_UnlockMutex(z_lock); return Mem_BlockToPtr(mem); }
/** * @brief Free memory blocks assigned to a specified tag within a pool */ void _Mem_FreeTag (memPool_t* pool, const int tagNum, const char* fileName, const int fileLine) { if (!pool) return; for (int j = 0; j < MEM_HASH; j++) { memBlock_t* mem, *next; for (mem = pool->blocks[j]; mem; mem = next) { next = mem->next; if (mem->tagNum == tagNum) _Mem_Free(Mem_BlockToPtr(mem), fileName, fileLine); } } }
/** * @brief Free all items within a pool * @sa _Mem_CreatePool * @sa _Mem_DeletePool */ void _Mem_FreePool (memPool_t* pool, const char* fileName, const int fileLine) { if (!pool) return; for (int j = 0; j < MEM_HASH; j++) { memBlock_t* mem, *next; for (mem = pool->blocks[j]; mem; mem = next) { next = mem->next; _Mem_Free(Mem_BlockToPtr(mem), fileName, fileLine); } } assert(pool->blockCount == 0); assert(pool->byteCount == 0); }
/** * Searches a given pointer in all memory pool blocks * @param pool The pool to search the pointer in * @param pointer The pointer to search in the pool */ bool _Mem_AllocatedInPool (memPool_t *pool, const void *pointer) { memBlock_t *mem; if (!pool) return false; /* if it's in the pool, it must be in THIS block */ mem = pool->blocks[(uintptr_t)pointer % MEM_HASH]; /* Cycle through the blocks */ for ( ; mem; mem = mem->next) { if (Mem_BlockToPtr(mem) == pointer) return true; } return false; }
static memBlockFoot_t *Mem_BlockToFooter(memBlock_t* const mem) { return reinterpret_cast<memBlockFoot_t*>(reinterpret_cast<byte*>(Mem_BlockToPtr(mem)) + mem->memSize); }