Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_mem.c (12572B)


      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 #include "qbsp.h"
     24 #include "l_log.h"
     25 
     26 int allocedmemory;
     27 
     28 //===========================================================================
     29 //
     30 // Parameter:				-
     31 // Returns:					-
     32 // Changes Globals:		-
     33 //===========================================================================
     34 void PrintMemorySize(unsigned long size)
     35 {
     36 	unsigned long number1, number2, number3;
     37 	number1 = size >> 20;
     38 	number2 = (size & 0xFFFFF) >> 10;
     39 	number3 = (size & 0x3FF);
     40 	if (number1) Log_Print("%ld MB", number1);
     41 	if (number1 && number2) Log_Print(" and ");
     42 	if (number2) Log_Print("%ld KB", number2);
     43 	if (number2 && number3) Log_Print(" and ");
     44 	if (number3) Log_Print("%ld bytes", number3);
     45 } //end of the function PrintFileSize
     46 
     47 #ifndef MEMDEBUG
     48 //===========================================================================
     49 //
     50 // Parameter:				-
     51 // Returns:					-
     52 // Changes Globals:		-
     53 //===========================================================================
     54 int MemorySize(void *ptr)
     55 {
     56 #if defined(WIN32) || defined(_WIN32)
     57 	#ifdef __WATCOMC__
     58 		//Intel 32 bits memory addressing, 16 bytes aligned
     59 	return (_msize(ptr) + 15) >> 4 << 4;
     60 	#else
     61 	return _msize(ptr);
     62 	#endif
     63 #else
     64 	return 0;
     65 #endif
     66 } //end of the function MemorySize
     67 //===========================================================================
     68 //
     69 // Parameter:				-
     70 // Returns:					-
     71 // Changes Globals:		-
     72 //===========================================================================
     73 void *GetClearedMemory(int size)
     74 {
     75 	void *ptr;
     76 
     77 	ptr = (void *) malloc(size);
     78 	if (!ptr) Error("out of memory");
     79 	memset(ptr, 0, size);
     80 	allocedmemory += MemorySize(ptr);
     81 	return ptr;
     82 } //end of the function GetClearedMemory
     83 //===========================================================================
     84 //
     85 // Parameter:				-
     86 // Returns:					-
     87 // Changes Globals:		-
     88 //===========================================================================
     89 void *GetMemory(unsigned long size)
     90 {
     91 	void *ptr;
     92 	ptr = malloc(size);
     93 	if (!ptr) Error("out of memory");
     94 	allocedmemory += MemorySize(ptr);
     95 	return ptr;
     96 } //end of the function GetMemory
     97 //===========================================================================
     98 //
     99 // Parameter:				-
    100 // Returns:					-
    101 // Changes Globals:		-
    102 //===========================================================================
    103 void FreeMemory(void *ptr)
    104 {
    105 	allocedmemory -= MemorySize(ptr);
    106 	free(ptr);
    107 } //end of the function FreeMemory
    108 //===========================================================================
    109 //
    110 // Parameter:				-
    111 // Returns:					-
    112 // Changes Globals:		-
    113 //===========================================================================
    114 int TotalAllocatedMemory(void)
    115 {
    116 	return allocedmemory;
    117 } //end of the function TotalAllocatedMemory
    118 
    119 #else
    120 
    121 #define MEM_ID		0x12345678l
    122 
    123 int totalmemorysize;
    124 int numblocks;
    125 
    126 typedef struct memoryblock_s
    127 {
    128 	unsigned long int id;
    129 	void *ptr;
    130 	int size;
    131 #ifdef MEMDEBUG
    132 	char *label;
    133 	char *file;
    134 	int line;
    135 #endif //MEMDEBUG
    136 	struct memoryblock_s *prev, *next;
    137 } memoryblock_t;
    138 
    139 memoryblock_t *memory;
    140 
    141 //===========================================================================
    142 //
    143 // Parameter:				-
    144 // Returns:					-
    145 // Changes Globals:		-
    146 //===========================================================================
    147 void LinkMemoryBlock(memoryblock_t *block)
    148 {
    149 	block->prev = NULL;
    150 	block->next = memory;
    151 	if (memory) memory->prev = block;
    152 	memory = block;
    153 } //end of the function LinkMemoryBlock
    154 //===========================================================================
    155 //
    156 // Parameter:				-
    157 // Returns:					-
    158 // Changes Globals:		-
    159 //===========================================================================
    160 void UnlinkMemoryBlock(memoryblock_t *block)
    161 {
    162 	if (block->prev) block->prev->next = block->next;
    163 	else memory = block->next;
    164 	if (block->next) block->next->prev = block->prev;
    165 } //end of the function UnlinkMemoryBlock
    166 //===========================================================================
    167 //
    168 // Parameter:				-
    169 // Returns:					-
    170 // Changes Globals:		-
    171 //===========================================================================
    172 #ifdef MEMDEBUG
    173 void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
    174 #else
    175 void *GetMemory(unsigned long size)
    176 #endif //MEMDEBUG
    177 {
    178 	void *ptr;
    179 	memoryblock_t *block;
    180 
    181 	ptr = malloc(size + sizeof(memoryblock_t));
    182 	block = (memoryblock_t *) ptr;
    183 	block->id = MEM_ID;
    184 	block->ptr = (char *) ptr + sizeof(memoryblock_t);
    185 	block->size = size + sizeof(memoryblock_t);
    186 #ifdef MEMDEBUG
    187 	block->label = label;
    188 	block->file = file;
    189 	block->line = line;
    190 #endif //MEMDEBUG
    191 	LinkMemoryBlock(block);
    192 	totalmemorysize += block->size;
    193 	numblocks++;
    194 	return block->ptr;
    195 } //end of the function GetMemoryDebug
    196 //===========================================================================
    197 //
    198 // Parameter:				-
    199 // Returns:					-
    200 // Changes Globals:		-
    201 //===========================================================================
    202 #ifdef MEMDEBUG
    203 void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
    204 #else
    205 void *GetClearedMemory(unsigned long size)
    206 #endif //MEMDEBUG
    207 {
    208 	void *ptr;
    209 #ifdef MEMDEBUG
    210 	ptr = GetMemoryDebug(size, label, file, line);
    211 #else
    212 	ptr = GetMemory(size);
    213 #endif //MEMDEBUG
    214 	memset(ptr, 0, size);
    215 	return ptr;
    216 } //end of the function GetClearedMemoryLabelled
    217 //===========================================================================
    218 //
    219 // Parameter:				-
    220 // Returns:					-
    221 // Changes Globals:		-
    222 //===========================================================================
    223 void *GetClearedHunkMemory(unsigned long size)
    224 {
    225 	return GetClearedMemory(size);
    226 } //end of the function GetClearedHunkMemory
    227 //===========================================================================
    228 //
    229 // Parameter:				-
    230 // Returns:					-
    231 // Changes Globals:		-
    232 //===========================================================================
    233 void *GetHunkMemory(unsigned long size)
    234 {
    235 	return GetMemory(size);
    236 } //end of the function GetHunkMemory
    237 //===========================================================================
    238 //
    239 // Parameter:				-
    240 // Returns:					-
    241 // Changes Globals:		-
    242 //===========================================================================
    243 memoryblock_t *BlockFromPointer(void *ptr, char *str)
    244 {
    245 	memoryblock_t *block;
    246 
    247 	if (!ptr)
    248 	{
    249 #ifdef MEMDEBUG
    250 		//char *crash = (char *) NULL;
    251 		//crash[0] = 1;
    252 		Error("%s: NULL pointer\n", str);
    253 #endif MEMDEBUG
    254 		return NULL;
    255 	} //end if
    256 	block = (memoryblock_t *) ((char *) ptr - sizeof(memoryblock_t));
    257 	if (block->id != MEM_ID)
    258 	{
    259 		Error("%s: invalid memory block\n", str);
    260 	} //end if
    261 	if (block->ptr != ptr)
    262 	{
    263 		
    264 		Error("%s: memory block pointer invalid\n", str);
    265 	} //end if
    266 	return block;
    267 } //end of the function BlockFromPointer
    268 //===========================================================================
    269 //
    270 // Parameter:				-
    271 // Returns:					-
    272 // Changes Globals:		-
    273 //===========================================================================
    274 void FreeMemory(void *ptr)
    275 {
    276 	memoryblock_t *block;
    277 
    278 	block = BlockFromPointer(ptr, "FreeMemory");
    279 	if (!block) return;
    280 	UnlinkMemoryBlock(block);
    281 	totalmemorysize -= block->size;
    282 	numblocks--;
    283 	//
    284 	free(block);
    285 } //end of the function FreeMemory
    286 //===========================================================================
    287 //
    288 // Parameter:				-
    289 // Returns:					-
    290 // Changes Globals:		-
    291 //===========================================================================
    292 int MemoryByteSize(void *ptr)
    293 {
    294 	memoryblock_t *block;
    295 
    296 	block = BlockFromPointer(ptr, "MemoryByteSize");
    297 	if (!block) return 0;
    298 	return block->size;
    299 } //end of the function MemoryByteSize
    300 //===========================================================================
    301 //
    302 // Parameter:				-
    303 // Returns:					-
    304 // Changes Globals:		-
    305 //===========================================================================
    306 int MemorySize(void *ptr)
    307 {
    308 	return MemoryByteSize(ptr);
    309 } //end of the function MemorySize
    310 //===========================================================================
    311 //
    312 // Parameter:				-
    313 // Returns:					-
    314 // Changes Globals:		-
    315 //===========================================================================
    316 void PrintUsedMemorySize(void)
    317 {
    318 	printf("total botlib memory: %d KB\n", totalmemorysize >> 10);
    319 	printf("total memory blocks: %d\n", numblocks);
    320 } //end of the function PrintUsedMemorySize
    321 //===========================================================================
    322 //
    323 // Parameter:				-
    324 // Returns:					-
    325 // Changes Globals:		-
    326 //===========================================================================
    327 void PrintMemoryLabels(void)
    328 {
    329 	memoryblock_t *block;
    330 	int i;
    331 
    332 	PrintUsedMemorySize();
    333 	i = 0;
    334 	for (block = memory; block; block = block->next)
    335 	{
    336 #ifdef MEMDEBUG
    337 		Log_Write("%6d, %p, %8d: %24s line %6d: %s", i, block->ptr, block->size, block->file, block->line, block->label);
    338 #endif //MEMDEBUG
    339 		i++;
    340 	} //end for
    341 } //end of the function PrintMemoryLabels
    342 //===========================================================================
    343 //
    344 // Parameter:				-
    345 // Returns:					-
    346 // Changes Globals:		-
    347 //===========================================================================
    348 void DumpMemory(void)
    349 {
    350 	memoryblock_t *block;
    351 
    352 	for (block = memory; block; block = memory)
    353 	{
    354 		FreeMemory(block->ptr);
    355 	} //end for
    356 	totalmemorysize = 0;
    357 } //end of the function DumpMemory
    358 //===========================================================================
    359 //
    360 // Parameter:				-
    361 // Returns:					-
    362 // Changes Globals:		-
    363 //===========================================================================
    364 int TotalAllocatedMemory(void)
    365 {
    366 	return totalmemorysize;
    367 } //end of the function TotalAllocatedMemory
    368 #endif
    369 
    370 //===========================================================================
    371 // Q3 Hunk and Z_ memory management
    372 //===========================================================================
    373 
    374 typedef struct memhunk_s
    375 {
    376 	void *ptr;
    377 	struct memhunk_s *next;
    378 } memhunk_t;
    379 
    380 memhunk_t *memhunk_high;
    381 memhunk_t *memhunk_low;
    382 int memhunk_high_size = 16 * 1024 * 1024;
    383 int memhunk_low_size = 0;
    384 
    385 //===========================================================================
    386 //
    387 // Parameter:				-
    388 // Returns:					-
    389 // Changes Globals:		-
    390 //===========================================================================
    391 void Hunk_ClearHigh(void)
    392 {
    393 	memhunk_t *h, *nexth;
    394 
    395 	for (h = memhunk_high; h; h = nexth)
    396 	{
    397 		nexth = h->next;
    398 		FreeMemory(h);
    399 	} //end for
    400 	memhunk_high = NULL;
    401 	memhunk_high_size = 16 * 1024 * 1024;
    402 } //end of the function Hunk_ClearHigh
    403 //===========================================================================
    404 //
    405 // Parameter:				-
    406 // Returns:					-
    407 // Changes Globals:		-
    408 //===========================================================================
    409 void *Hunk_Alloc(int size)
    410 {
    411 	memhunk_t *h;
    412 
    413 	if (!size) return (void *) memhunk_high_size;
    414 	//
    415 	h = GetClearedMemory(size + sizeof(memhunk_t));
    416 	h->ptr = (char *) h + sizeof(memhunk_t);
    417 	h->next = memhunk_high;
    418 	memhunk_high = h;
    419 	memhunk_high_size -= size;
    420 	return h->ptr;
    421 } //end of the function Hunk_Alloc
    422 //===========================================================================
    423 //
    424 // Parameter:				-
    425 // Returns:					-
    426 // Changes Globals:		-
    427 //===========================================================================
    428 void *Z_Malloc(int size)
    429 {
    430 	return GetClearedMemory(size);
    431 } //end of the function Z_Malloc
    432 //===========================================================================
    433 //
    434 // Parameter:				-
    435 // Returns:					-
    436 // Changes Globals:		-
    437 //===========================================================================
    438 void Z_Free (void *ptr)
    439 {
    440 	FreeMemory(ptr);
    441 } //end of the function Z_Free