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