30 #include <SDL_thread.h>
32 #define MEM_MAX_POOLNAME 64
68 #define MEM_HEAD_SENTINEL_TOP 0xFEBDFAED
69 #define MEM_HEAD_SENTINEL_BOT 0xD0BAF0FF
70 #define MEM_FOOT_SENTINEL 0xF00DF00D
74 #define MEM_MAX_POOLCOUNT 32
88 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
106 if (!name || !name[0])
107 Sys_Error(
"Mem_CreatePool: nullptr name %s:#%i", fileName, fileLine);
109 Com_Printf(
"Mem_CreatePoole: name '%s' too long, truncating!\n", name);
118 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
122 if (i == m_numPools) {
124 Sys_Error(
"Mem_CreatePool: MEM_MAX_POOLCOUNT");
125 pool = &m_poolList[m_numPools++];
130 pool->
blocks[i] =
nullptr;
156 pool->
name[0] =
'\0';
187 Sys_Error(
"Mem_CheckSentinels: bad memory header top sentinel [buffer underflow]\n"
188 "free: %s:#%i", fileName, fileLine);
190 Sys_Error(
"Mem_CheckSentinels: bad memory header bottom sentinel [buffer underflow]\n"
191 "free: %s:#%i", fileName, fileLine);
193 Sys_Error(
"Mem_CheckSentinels: bad memory footer sentinel [buffer overflow]\n"
204 void _Mem_Free (
void* ptr,
const char* fileName,
const int fileLine)
226 *prev = search->
next;
229 prev = &search->
next;
246 for (
int j = 0; j <
MEM_HASH; j++) {
249 if (mem->tagNum == tagNum)
265 for (
int j = 0; j <
MEM_HASH; j++) {
283 Sys_Error(
"Mem_Alloc: Error - no pool given\n" "alloc: %s:#%i", fileName, fileLine);
287 Sys_Error(
"Mem_Alloc: Attempted allocation of '" UFO_SIZE_T "' memory ignored\n" "alloc: %s:#%i", size, fileName, fileLine);
289 if (size > 0x40000000)
290 Sys_Error(
"Mem_Alloc: Attempted allocation of '" UFO_SIZE_T "' bytes!\n" "alloc: %s:#%i", size, fileName, fileLine);
296 Sys_Error(
"Mem_Alloc: failed on allocation of '" UFO_SIZE_T "' bytes\n" "alloc: %s:#%i", size, fileName, fileLine);
300 memset(mem, 0, size);
347 void* newPtr =
_Mem_Alloc(size,
false, pool, mem->
tagNum, fileName, fileLine);
350 memcpy(newPtr, ptr, std::min(mem->
memSize, size));
352 const size_t delta = size - mem->
memSize;
387 assert(in !=
nullptr);
390 void* copy =
_Mem_Alloc(size,
false, pool, tagNum, fileName, fileLine);
391 memcpy(copy, in, size);
405 char* out = (
char*)
_Mem_Alloc((
size_t)(strlen(in) + 1),
true, pool, tagNum, fileName, fileLine);
427 uint32_t numChanged = 0;
429 for (
int j = 0; j <
MEM_HASH; j++) {
431 if (mem->tagNum == tagFrom) {
452 for (j = 0, blocks = 0, size = 0; j <
MEM_HASH; j++) {
461 Sys_Error(
"Mem_CheckPoolIntegrity: bad block count\n" "check: %s:#%i", fileName, fileLine);
463 Sys_Error(
"Mem_CheckPoolIntegrity: bad pool size\n" "check: %s:#%i", fileName, fileLine);
471 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
490 for ( ; mem; mem = mem->
next) {
503 static void Mem_Check_f (
void)
508 static void Mem_Stats_f (
void)
510 uint32_t totalBytes,
i;
518 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
536 Com_Printf(
"----- ----- -------------------- ---------- \n");
538 uint32_t totalBytes = 0;
541 for (i = 0, mem = best->
blocks[j]; mem; mem = mem->
next, i++) {
553 Com_Printf(
"----------------------------------------\n");
554 Com_Printf(
"Total: %i blocks, %i bytes (%6.3fMB)\n", i, totalBytes, totalBytes/1048576.0
f);
560 Com_Printf(
"--- ------ ---------- ---------- --------\n");
562 uint32_t totalBlocks = 0;
564 uint32_t poolNum = 0;
565 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
579 Com_Printf(
"----------------------------------------\n");
580 Com_Printf(
"Total: %i pools, %i blocks, %i bytes (%6.3fMB)\n", i, totalBlocks, totalBytes, totalBytes/1048576.0
f);
591 Cmd_AddCommand(
"mem_stats", Mem_Stats_f,
"Prints out current internal memory statistics");
592 Cmd_AddCommand(
"mem_check", Mem_Check_f,
"Checks global memory integrity");
595 z_lock = SDL_CreateMutex();
610 for (i = 0, pool = &m_poolList[0]; i <
m_numPools; pool++, i++) {
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
void Sys_Error(const char *error,...)
#define MEM_HEAD_SENTINEL_BOT
static void * Mem_BlockToPtr(memBlock_t *const mem)
void * _Mem_PoolDup(const void *in, size_t size, memPool_t *pool, const int tagNum, const char *fileName, const int fileLine)
static uint32_t m_numPools
void * _Mem_Alloc(size_t size, bool zeroFill, memPool_t *pool, const int tagNum, const char *fileName, const int fileLine)
Optionally returns 0 filled memory allocated in a pool with a tag.
QGL_EXTERN GLint GLenum GLboolean GLsizei const GLvoid * pointer
static memPool_t * Mem_FindPool(const char *name)
#define MEM_MAX_POOLCOUNT
#define MEM_FOOT_SENTINEL
void Com_Printf(const char *const fmt,...)
uint32_t _Mem_PoolSize(memPool_t *pool)
uint32_t _Mem_ChangeTag(memPool_t *pool, const int tagFrom, const int tagTo)
char * _Mem_PoolStrDupTo(const char *in, char **out, memPool_t *pool, const int tagNum, const char *fileName, const int fileLine)
Saves a string to client hunk.
#define Mem_CheckGlobalIntegrity()
static memBlockFoot_t * Mem_BlockToFooter(memBlock_t *const mem)
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
bool _Mem_AllocatedInPool(memPool_t *pool, const void *pointer)
void _Mem_Free(void *ptr, const char *fileName, const int fileLine)
void _Mem_CheckGlobalIntegrity(const char *fileName, const int fileLine)
static void _Mem_CheckSentinels(memBlock_t *const mem, const char *fileName, const int fileLine)
void _Mem_FreePool(memPool_t *pool, const char *fileName, const int fileLine)
Free all items within a pool.
static size_t Mem_BlockRawSize(memBlock_t const *const mem)
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
static void _Mem_CheckPoolIntegrity(memPool_t *pool, const char *fileName, const int fileLine)
#define Mem_DeletePool(pool)
#define MEM_HEAD_SENTINEL_TOP
void * _Mem_ReAlloc(void *ptr, size_t size, const char *fileName, const int fileLine)
static memBlock_t * Mem_PtrToBlock(void *const ptr)
memPool_t * _Mem_CreatePool(const char *name, const char *fileName, const int fileLine)
static SDL_mutex * z_lock
char * _Mem_PoolStrDup(const char *in, memPool_t *pool, const int tagNum, const char *fileName, const int fileLine)
No need to null terminate the extra spot because Mem_Alloc returns zero-filled memory.
char name[MEM_MAX_POOLNAME]
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
definitions common between client and server, but not game lib
memBlock_t * blocks[MEM_HASH]
void _Mem_FreeTag(memPool_t *pool, const int tagNum, const char *fileName, const int fileLine)
Free memory blocks assigned to a specified tag within a pool.
const char * Cmd_Args(void)
Returns a single string containing argv(1) to argv(argc()-1)
void _Mem_DeletePool(memPool_t *pool, const char *fileName, const int fileLine)
static memPool_t m_poolList[MEM_MAX_POOLCOUNT]