/* =========================================================================== Return to Castle Wolfenstein single player GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). RTCW SP Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RTCW SP Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RTCW SP Source Code. If not, see . In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ //=========================================================================== // // Name: l_mem.c // Function: // Programmer: Mr Elusive (MrElusive@demigod.demon.nl) // Last update: 1999-06-02 // Tab Size: 3 //=========================================================================== #include "qbsp.h" #include "l_log.h" int allocedmemory; //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void PrintMemorySize( unsigned long size ) { unsigned long number1, number2, number3; number1 = size >> 20; number2 = ( size & 0xFFFFF ) >> 10; number3 = ( size & 0x3FF ); if ( number1 ) { Log_Print( "%ld MB", number1 ); } if ( number1 && number2 ) { Log_Print( " and " ); } if ( number2 ) { Log_Print( "%ld KB", number2 ); } if ( number2 && number3 ) { Log_Print( " and " ); } if ( number3 ) { Log_Print( "%ld bytes", number3 ); } } //end of the function PrintFileSize #ifndef MEMDEBUG //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int MemorySize( void *ptr ) { #if defined( WIN32 ) || defined( _WIN32 ) #ifdef __WATCOMC__ //Intel 32 bits memory addressing, 16 bytes aligned return ( _msize( ptr ) + 15 ) >> 4 << 4; #else return _msize( ptr ); #endif #else return 0; #endif } //end of the function MemorySize //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *GetClearedMemory( int size ) { void *ptr; ptr = (void *) malloc( size ); if ( !ptr ) { Error( "out of memory" ); } memset( ptr, 0, size ); allocedmemory += MemorySize( ptr ); return ptr; } //end of the function GetClearedMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *GetMemory( unsigned long size ) { void *ptr; ptr = malloc( size ); if ( !ptr ) { Error( "out of memory" ); } allocedmemory += MemorySize( ptr ); return ptr; } //end of the function GetMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int fmemsize; void FreeMemory( void *ptr ) { // RF, modified this for better memory trash testing fmemsize = MemorySize( ptr ); allocedmemory -= fmemsize; // RF, somehow this crashes windows if size is less than or equal 8 if ( fmemsize <= 8 ) { return; } // RF, set this memory to something that will cause problems if accessed again memset( ptr, 0xAA, fmemsize ); free( ptr ); } //end of the function FreeMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int TotalAllocatedMemory( void ) { return allocedmemory; } //end of the function TotalAllocatedMemory #else #define MEM_ID 0x12345678l int totalmemorysize; int numblocks; typedef struct memoryblock_s { unsigned long int id; void *ptr; int size; #ifdef MEMDEBUG char *label; char *file; int line; #endif //MEMDEBUG struct memoryblock_s *prev, *next; } memoryblock_t; memoryblock_t *memory; //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void LinkMemoryBlock( memoryblock_t *block ) { block->prev = NULL; block->next = memory; if ( memory ) { memory->prev = block; } memory = block; } //end of the function LinkMemoryBlock //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void UnlinkMemoryBlock( memoryblock_t *block ) { if ( block->prev ) { block->prev->next = block->next; } else { memory = block->next;} if ( block->next ) { block->next->prev = block->prev; } } //end of the function UnlinkMemoryBlock //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== #ifdef MEMDEBUG void *GetMemoryDebug( unsigned long size, char *label, char *file, int line ) #else void *GetMemory( unsigned long size ) #endif //MEMDEBUG { void *ptr; memoryblock_t *block; ptr = malloc( size + sizeof( memoryblock_t ) ); block = (memoryblock_t *) ptr; block->id = MEM_ID; block->ptr = (char *) ptr + sizeof( memoryblock_t ); block->size = size + sizeof( memoryblock_t ); #ifdef MEMDEBUG block->label = label; block->file = file; block->line = line; #endif //MEMDEBUG LinkMemoryBlock( block ); totalmemorysize += block->size; numblocks++; return block->ptr; } //end of the function GetMemoryDebug //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== #ifdef MEMDEBUG void *GetClearedMemoryDebug( unsigned long size, char *label, char *file, int line ) #else void *GetClearedMemory( unsigned long size ) #endif //MEMDEBUG { void *ptr; #ifdef MEMDEBUG ptr = GetMemoryDebug( size, label, file, line ); #else ptr = GetMemory( size ); #endif //MEMDEBUG memset( ptr, 0, size ); return ptr; } //end of the function GetClearedMemoryLabelled //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *GetClearedHunkMemory( unsigned long size ) { return GetClearedMemory( size ); } //end of the function GetClearedHunkMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *GetHunkMemory( unsigned long size ) { return GetMemory( size ); } //end of the function GetHunkMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== memoryblock_t *BlockFromPointer( void *ptr, char *str ) { memoryblock_t *block; if ( !ptr ) { #ifdef MEMDEBUG //char *crash = (char *) NULL; //crash[0] = 1; Error( "%s: NULL pointer\n", str ); #endif MEMDEBUG return NULL; } //end if block = ( memoryblock_t * )( (char *) ptr - sizeof( memoryblock_t ) ); if ( block->id != MEM_ID ) { Error( "%s: invalid memory block\n", str ); } //end if if ( block->ptr != ptr ) { Error( "%s: memory block pointer invalid\n", str ); } //end if return block; } //end of the function BlockFromPointer //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void FreeMemory( void *ptr ) { memoryblock_t *block; block = BlockFromPointer( ptr, "FreeMemory" ); if ( !block ) { return; } UnlinkMemoryBlock( block ); totalmemorysize -= block->size; numblocks--; // free( block ); } //end of the function FreeMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int MemoryByteSize( void *ptr ) { memoryblock_t *block; block = BlockFromPointer( ptr, "MemoryByteSize" ); if ( !block ) { return 0; } return block->size; } //end of the function MemoryByteSize //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int MemorySize( void *ptr ) { return MemoryByteSize( ptr ); } //end of the function MemorySize //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void PrintUsedMemorySize( void ) { printf( "total botlib memory: %d KB\n", totalmemorysize >> 10 ); printf( "total memory blocks: %d\n", numblocks ); } //end of the function PrintUsedMemorySize //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void PrintMemoryLabels( void ) { memoryblock_t *block; int i; PrintUsedMemorySize(); i = 0; for ( block = memory; block; block = block->next ) { #ifdef MEMDEBUG Log_Write( "%6d, %p, %8d: %24s line %6d: %s", i, block->ptr, block->size, block->file, block->line, block->label ); #endif //MEMDEBUG i++; } //end for } //end of the function PrintMemoryLabels //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void DumpMemory( void ) { memoryblock_t *block; for ( block = memory; block; block = memory ) { FreeMemory( block->ptr ); } //end for totalmemorysize = 0; } //end of the function DumpMemory //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int TotalAllocatedMemory( void ) { return totalmemorysize; } //end of the function TotalAllocatedMemory #endif //=========================================================================== // Q3 Hunk and Z_ memory management //=========================================================================== typedef struct memhunk_s { void *ptr; struct memhunk_s *next; } memhunk_t; memhunk_t *memhunk_high; memhunk_t *memhunk_low; int memhunk_high_size = 16 * 1024 * 1024; int memhunk_low_size = 0; //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Hunk_ClearHigh( void ) { memhunk_t *h, *nexth; for ( h = memhunk_high; h; h = nexth ) { nexth = h->next; FreeMemory( h ); } //end for memhunk_high = NULL; memhunk_high_size = 16 * 1024 * 1024; } //end of the function Hunk_ClearHigh //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *Hunk_Alloc( int size ) { memhunk_t *h; if ( !size ) { return (void *) memhunk_high_size; } // h = GetClearedMemory( size + sizeof( memhunk_t ) ); h->ptr = (char *) h + sizeof( memhunk_t ); h->next = memhunk_high; memhunk_high = h; memhunk_high_size -= size; return h->ptr; } //end of the function Hunk_Alloc //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void *Z_Malloc( int size ) { return GetClearedMemory( size ); } //end of the function Z_Malloc //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void Z_Free( void *ptr ) { FreeMemory( ptr ); } //end of the function Z_Free