Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_memory.c (13574B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 /*****************************************************************************
     24  * name:		l_memory.c
     25  *
     26  * desc:		memory allocation
     27  *
     28  * $Archive: /MissionPack/code/botlib/l_memory.c $
     29  *
     30  *****************************************************************************/
     31 
     32 #include "../game/q_shared.h"
     33 #include "../game/botlib.h"
     34 #include "l_log.h"
     35 #include "be_interface.h"
     36 
     37 //#define MEMDEBUG
     38 //#define MEMORYMANEGER
     39 
     40 #define MEM_ID		0x12345678l
     41 #define HUNK_ID		0x87654321l
     42 
     43 int allocatedmemory;
     44 int totalmemorysize;
     45 int numblocks;
     46 
     47 #ifdef MEMORYMANEGER
     48 
     49 typedef struct memoryblock_s
     50 {
     51 	unsigned long int id;
     52 	void *ptr;
     53 	int size;
     54 #ifdef MEMDEBUG
     55 	char *label;
     56 	char *file;
     57 	int line;
     58 #endif //MEMDEBUG
     59 	struct memoryblock_s *prev, *next;
     60 } memoryblock_t;
     61 
     62 memoryblock_t *memory;
     63 
     64 //===========================================================================
     65 //
     66 // Parameter:			-
     67 // Returns:				-
     68 // Changes Globals:		-
     69 //===========================================================================
     70 void LinkMemoryBlock(memoryblock_t *block)
     71 {
     72 	block->prev = NULL;
     73 	block->next = memory;
     74 	if (memory) memory->prev = block;
     75 	memory = block;
     76 } //end of the function LinkMemoryBlock
     77 //===========================================================================
     78 //
     79 // Parameter:			-
     80 // Returns:				-
     81 // Changes Globals:		-
     82 //===========================================================================
     83 void UnlinkMemoryBlock(memoryblock_t *block)
     84 {
     85 	if (block->prev) block->prev->next = block->next;
     86 	else memory = block->next;
     87 	if (block->next) block->next->prev = block->prev;
     88 } //end of the function UnlinkMemoryBlock
     89 //===========================================================================
     90 //
     91 // Parameter:			-
     92 // Returns:				-
     93 // Changes Globals:		-
     94 //===========================================================================
     95 #ifdef MEMDEBUG
     96 void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
     97 #else
     98 void *GetMemory(unsigned long size)
     99 #endif //MEMDEBUG
    100 {
    101 	void *ptr;
    102 	memoryblock_t *block;
    103   assert(botimport.GetMemory); // bk001129 - was NULL'ed
    104 	ptr = botimport.GetMemory(size + sizeof(memoryblock_t));
    105 	block = (memoryblock_t *) ptr;
    106 	block->id = MEM_ID;
    107 	block->ptr = (char *) ptr + sizeof(memoryblock_t);
    108 	block->size = size + sizeof(memoryblock_t);
    109 #ifdef MEMDEBUG
    110 	block->label = label;
    111 	block->file = file;
    112 	block->line = line;
    113 #endif //MEMDEBUG
    114 	LinkMemoryBlock(block);
    115 	allocatedmemory += block->size;
    116 	totalmemorysize += block->size + sizeof(memoryblock_t);
    117 	numblocks++;
    118 	return block->ptr;
    119 } //end of the function GetMemoryDebug
    120 //===========================================================================
    121 //
    122 // Parameter:			-
    123 // Returns:				-
    124 // Changes Globals:		-
    125 //===========================================================================
    126 #ifdef MEMDEBUG
    127 void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
    128 #else
    129 void *GetClearedMemory(unsigned long size)
    130 #endif //MEMDEBUG
    131 {
    132 	void *ptr;
    133 #ifdef MEMDEBUG
    134 	ptr = GetMemoryDebug(size, label, file, line);
    135 #else
    136 	ptr = GetMemory(size);
    137 #endif //MEMDEBUG
    138 	Com_Memset(ptr, 0, size);
    139 	return ptr;
    140 } //end of the function GetClearedMemory
    141 //===========================================================================
    142 //
    143 // Parameter:			-
    144 // Returns:				-
    145 // Changes Globals:		-
    146 //===========================================================================
    147 #ifdef MEMDEBUG
    148 void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
    149 #else
    150 void *GetHunkMemory(unsigned long size)
    151 #endif //MEMDEBUG
    152 {
    153 	void *ptr;
    154 	memoryblock_t *block;
    155 
    156 	ptr = botimport.HunkAlloc(size + sizeof(memoryblock_t));
    157 	block = (memoryblock_t *) ptr;
    158 	block->id = HUNK_ID;
    159 	block->ptr = (char *) ptr + sizeof(memoryblock_t);
    160 	block->size = size + sizeof(memoryblock_t);
    161 #ifdef MEMDEBUG
    162 	block->label = label;
    163 	block->file = file;
    164 	block->line = line;
    165 #endif //MEMDEBUG
    166 	LinkMemoryBlock(block);
    167 	allocatedmemory += block->size;
    168 	totalmemorysize += block->size + sizeof(memoryblock_t);
    169 	numblocks++;
    170 	return block->ptr;
    171 } //end of the function GetHunkMemoryDebug
    172 //===========================================================================
    173 //
    174 // Parameter:			-
    175 // Returns:				-
    176 // Changes Globals:		-
    177 //===========================================================================
    178 #ifdef MEMDEBUG
    179 void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
    180 #else
    181 void *GetClearedHunkMemory(unsigned long size)
    182 #endif //MEMDEBUG
    183 {
    184 	void *ptr;
    185 #ifdef MEMDEBUG
    186 	ptr = GetHunkMemoryDebug(size, label, file, line);
    187 #else
    188 	ptr = GetHunkMemory(size);
    189 #endif //MEMDEBUG
    190 	Com_Memset(ptr, 0, size);
    191 	return ptr;
    192 } //end of the function GetClearedHunkMemory
    193 //===========================================================================
    194 //
    195 // Parameter:			-
    196 // Returns:				-
    197 // Changes Globals:		-
    198 //===========================================================================
    199 memoryblock_t *BlockFromPointer(void *ptr, char *str)
    200 {
    201 	memoryblock_t *block;
    202 
    203 	if (!ptr)
    204 	{
    205 #ifdef MEMDEBUG
    206 		//char *crash = (char *) NULL;
    207 		//crash[0] = 1;
    208 		botimport.Print(PRT_FATAL, "%s: NULL pointer\n", str);
    209 #endif // MEMDEBUG
    210 		return NULL;
    211 	} //end if
    212 	block = (memoryblock_t *) ((char *) ptr - sizeof(memoryblock_t));
    213 	if (block->id != MEM_ID && block->id != HUNK_ID)
    214 	{
    215 		botimport.Print(PRT_FATAL, "%s: invalid memory block\n", str);
    216 		return NULL;
    217 	} //end if
    218 	if (block->ptr != ptr)
    219 	{
    220 		botimport.Print(PRT_FATAL, "%s: memory block pointer invalid\n", str);
    221 		return NULL;
    222 	} //end if
    223 	return block;
    224 } //end of the function BlockFromPointer
    225 //===========================================================================
    226 //
    227 // Parameter:			-
    228 // Returns:				-
    229 // Changes Globals:		-
    230 //===========================================================================
    231 void FreeMemory(void *ptr)
    232 {
    233 	memoryblock_t *block;
    234 
    235 	block = BlockFromPointer(ptr, "FreeMemory");
    236 	if (!block) return;
    237 	UnlinkMemoryBlock(block);
    238 	allocatedmemory -= block->size;
    239 	totalmemorysize -= block->size + sizeof(memoryblock_t);
    240 	numblocks--;
    241 	//
    242 	if (block->id == MEM_ID)
    243 	{
    244 		botimport.FreeMemory(block);
    245 	} //end if
    246 } //end of the function FreeMemory
    247 //===========================================================================
    248 //
    249 // Parameter:			-
    250 // Returns:				-
    251 // Changes Globals:		-
    252 //===========================================================================
    253 int AvailableMemory(void)
    254 {
    255 	return botimport.AvailableMemory();
    256 } //end of the function AvailableMemory
    257 //===========================================================================
    258 //
    259 // Parameter:			-
    260 // Returns:				-
    261 // Changes Globals:		-
    262 //===========================================================================
    263 int MemoryByteSize(void *ptr)
    264 {
    265 	memoryblock_t *block;
    266 
    267 	block = BlockFromPointer(ptr, "MemoryByteSize");
    268 	if (!block) return 0;
    269 	return block->size;
    270 } //end of the function MemoryByteSize
    271 //===========================================================================
    272 //
    273 // Parameter:			-
    274 // Returns:				-
    275 // Changes Globals:		-
    276 //===========================================================================
    277 void PrintUsedMemorySize(void)
    278 {
    279 	botimport.Print(PRT_MESSAGE, "total allocated memory: %d KB\n", allocatedmemory >> 10);
    280 	botimport.Print(PRT_MESSAGE, "total botlib memory: %d KB\n", totalmemorysize >> 10);
    281 	botimport.Print(PRT_MESSAGE, "total memory blocks: %d\n", numblocks);
    282 } //end of the function PrintUsedMemorySize
    283 //===========================================================================
    284 //
    285 // Parameter:			-
    286 // Returns:				-
    287 // Changes Globals:		-
    288 //===========================================================================
    289 void PrintMemoryLabels(void)
    290 {
    291 	memoryblock_t *block;
    292 	int i;
    293 
    294 	PrintUsedMemorySize();
    295 	i = 0;
    296 	Log_Write("============= Botlib memory log ==============\r\n");
    297 	Log_Write("\r\n");
    298 	for (block = memory; block; block = block->next)
    299 	{
    300 #ifdef MEMDEBUG
    301 		if (block->id == HUNK_ID)
    302 		{
    303 			Log_Write("%6d, hunk %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
    304 		} //end if
    305 		else
    306 		{
    307 			Log_Write("%6d,      %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
    308 		} //end else
    309 #endif //MEMDEBUG
    310 		i++;
    311 	} //end for
    312 } //end of the function PrintMemoryLabels
    313 //===========================================================================
    314 //
    315 // Parameter:			-
    316 // Returns:				-
    317 // Changes Globals:		-
    318 //===========================================================================
    319 void DumpMemory(void)
    320 {
    321 	memoryblock_t *block;
    322 
    323 	for (block = memory; block; block = memory)
    324 	{
    325 		FreeMemory(block->ptr);
    326 	} //end for
    327 	totalmemorysize = 0;
    328 	allocatedmemory = 0;
    329 } //end of the function DumpMemory
    330 
    331 #else
    332 
    333 //===========================================================================
    334 //
    335 // Parameter:			-
    336 // Returns:				-
    337 // Changes Globals:		-
    338 //===========================================================================
    339 #ifdef MEMDEBUG
    340 void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
    341 #else
    342 void *GetMemory(unsigned long size)
    343 #endif //MEMDEBUG
    344 {
    345 	void *ptr;
    346 	unsigned long int *memid;
    347 
    348 	ptr = botimport.GetMemory(size + sizeof(unsigned long int));
    349 	if (!ptr) return NULL;
    350 	memid = (unsigned long int *) ptr;
    351 	*memid = MEM_ID;
    352 	return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
    353 } //end of the function GetMemory
    354 //===========================================================================
    355 //
    356 // Parameter:			-
    357 // Returns:				-
    358 // Changes Globals:		-
    359 //===========================================================================
    360 #ifdef MEMDEBUG
    361 void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
    362 #else
    363 void *GetClearedMemory(unsigned long size)
    364 #endif //MEMDEBUG
    365 {
    366 	void *ptr;
    367 #ifdef MEMDEBUG
    368 	ptr = GetMemoryDebug(size, label, file, line);
    369 #else
    370 	ptr = GetMemory(size);
    371 #endif //MEMDEBUG
    372 	Com_Memset(ptr, 0, size);
    373 	return ptr;
    374 } //end of the function GetClearedMemory
    375 //===========================================================================
    376 //
    377 // Parameter:			-
    378 // Returns:				-
    379 // Changes Globals:		-
    380 //===========================================================================
    381 #ifdef MEMDEBUG
    382 void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
    383 #else
    384 void *GetHunkMemory(unsigned long size)
    385 #endif //MEMDEBUG
    386 {
    387 	void *ptr;
    388 	unsigned long int *memid;
    389 
    390 	ptr = botimport.HunkAlloc(size + sizeof(unsigned long int));
    391 	if (!ptr) return NULL;
    392 	memid = (unsigned long int *) ptr;
    393 	*memid = HUNK_ID;
    394 	return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
    395 } //end of the function GetHunkMemory
    396 //===========================================================================
    397 //
    398 // Parameter:			-
    399 // Returns:				-
    400 // Changes Globals:		-
    401 //===========================================================================
    402 #ifdef MEMDEBUG
    403 void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
    404 #else
    405 void *GetClearedHunkMemory(unsigned long size)
    406 #endif //MEMDEBUG
    407 {
    408 	void *ptr;
    409 #ifdef MEMDEBUG
    410 	ptr = GetHunkMemoryDebug(size, label, file, line);
    411 #else
    412 	ptr = GetHunkMemory(size);
    413 #endif //MEMDEBUG
    414 	Com_Memset(ptr, 0, size);
    415 	return ptr;
    416 } //end of the function GetClearedHunkMemory
    417 //===========================================================================
    418 //
    419 // Parameter:			-
    420 // Returns:				-
    421 // Changes Globals:		-
    422 //===========================================================================
    423 void FreeMemory(void *ptr)
    424 {
    425 	unsigned long int *memid;
    426 
    427 	memid = (unsigned long int *) ((char *) ptr - sizeof(unsigned long int));
    428 
    429 	if (*memid == MEM_ID)
    430 	{
    431 		botimport.FreeMemory(memid);
    432 	} //end if
    433 } //end of the function FreeMemory
    434 //===========================================================================
    435 //
    436 // Parameter:			-
    437 // Returns:				-
    438 // Changes Globals:		-
    439 //===========================================================================
    440 int AvailableMemory(void)
    441 {
    442 	return botimport.AvailableMemory();
    443 } //end of the function AvailableMemory
    444 //===========================================================================
    445 //
    446 // Parameter:			-
    447 // Returns:				-
    448 // Changes Globals:		-
    449 //===========================================================================
    450 void PrintUsedMemorySize(void)
    451 {
    452 } //end of the function PrintUsedMemorySize
    453 //===========================================================================
    454 //
    455 // Parameter:			-
    456 // Returns:				-
    457 // Changes Globals:		-
    458 //===========================================================================
    459 void PrintMemoryLabels(void)
    460 {
    461 } //end of the function PrintMemoryLabels
    462 
    463 #endif