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