You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.1 KiB
169 lines
4.1 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// ZONE MEMORY ALLOCATION |
|
// |
|
// There is never any space between memblocks, and there will never be two |
|
// contiguous free memblocks. |
|
// |
|
// The rover can be left pointing at a non-empty block |
|
// |
|
// The zone calls are pretty much only used for small strings and structures, |
|
// all big things are allocated on the hunk. |
|
//=============================================================================// |
|
|
|
#include "basetypes.h" |
|
#include "zone.h" |
|
#include "host.h" |
|
#include "tier1/strtools.h" |
|
#include "tier0/icommandline.h" |
|
#include "memstack.h" |
|
#include "datacache/idatacache.h" |
|
#include "sys_dll.h" |
|
#include "tier0/memalloc.h" |
|
|
|
#define MINIMUM_WIN_MEMORY 0x03000000 // FIXME: copy from sys_dll.cpp, find a common header at some point |
|
|
|
#ifdef _X360 |
|
#define HUNK_USE_16MB_PAGE |
|
#endif |
|
|
|
CMemoryStack g_HunkMemoryStack; |
|
#ifdef HUNK_USE_16MB_PAGE |
|
CMemoryStack g_HunkOverflow; |
|
static bool g_bWarnedOverflow; |
|
#endif |
|
|
|
static int GetTargetCacheSize() |
|
{ |
|
int nMemLimit = host_parms.memsize - Hunk_Size(); |
|
if ( nMemLimit < 0x100000 ) |
|
{ |
|
nMemLimit = 0x100000; |
|
} |
|
return nMemLimit; |
|
} |
|
|
|
/* |
|
=================== |
|
Hunk_AllocName |
|
=================== |
|
*/ |
|
void *Hunk_AllocName (int size, const char *name, bool bClear) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
void * p = g_HunkMemoryStack.Alloc( size, bClear ); |
|
if ( p ) |
|
return p; |
|
#ifdef HUNK_USE_16MB_PAGE |
|
if ( !g_bWarnedOverflow ) |
|
{ |
|
g_bWarnedOverflow = true; |
|
DevMsg( "Note: Hunk base page exhausted\n" ); |
|
} |
|
|
|
p = g_HunkOverflow.Alloc( size, bClear ); |
|
if ( p ) |
|
return p; |
|
#endif |
|
Error( "Engine hunk overflow!\n" ); |
|
return NULL; |
|
} |
|
|
|
/* |
|
=================== |
|
Hunk_Alloc |
|
=================== |
|
*/ |
|
void *Hunk_Alloc(int size, bool bClear ) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
return Hunk_AllocName( size, NULL, bClear ); |
|
} |
|
|
|
int Hunk_LowMark(void) |
|
{ |
|
return (int)( g_HunkMemoryStack.GetCurrentAllocPoint() ); |
|
} |
|
|
|
void Hunk_FreeToLowMark(int mark) |
|
{ |
|
Assert( mark < g_HunkMemoryStack.GetSize() ); |
|
#ifdef HUNK_USE_16MB_PAGE |
|
g_HunkOverflow.FreeAll(); |
|
g_bWarnedOverflow = false; |
|
#endif |
|
g_HunkMemoryStack.FreeToAllocPoint( mark ); |
|
} |
|
|
|
int Hunk_MallocSize() |
|
{ |
|
#ifdef HUNK_USE_16MB_PAGE |
|
return g_HunkMemoryStack.GetSize() + g_HunkOverflow.GetSize(); |
|
#else |
|
return g_HunkMemoryStack.GetSize(); |
|
#endif |
|
} |
|
|
|
int Hunk_Size() |
|
{ |
|
#ifdef HUNK_USE_16MB_PAGE |
|
return g_HunkMemoryStack.GetUsed() + g_HunkOverflow.GetUsed(); |
|
#else |
|
return g_HunkMemoryStack.GetUsed(); |
|
#endif |
|
} |
|
|
|
void Hunk_Print() |
|
{ |
|
#ifdef HUNK_USE_16MB_PAGE |
|
Msg( "Total used memory: %d (%d/%d)\n", Hunk_Size(), g_HunkMemoryStack.GetUsed(), g_HunkOverflow.GetUsed() ); |
|
Msg( "Total committed memory: %d (%d/%d)\n", Hunk_MallocSize(), g_HunkMemoryStack.GetSize(), g_HunkOverflow.GetSize() ); |
|
#else |
|
Msg( "Total used memory: %d\n", Hunk_Size() ); |
|
Msg( "Total committed memory: %d\n", Hunk_MallocSize() ); |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void Memory_Init( void ) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
int nMaxBytes = 48*1024*1024; |
|
const int nMinCommitBytes = 0x8000; |
|
#ifndef HUNK_USE_16MB_PAGE |
|
const int nInitialCommit = 0x280000; |
|
while ( !g_HunkMemoryStack.Init( nMaxBytes, nMinCommitBytes, nInitialCommit ) ) |
|
{ |
|
Warning( "Unable to allocate %d MB of memory, trying %d MB instead\n", nMaxBytes, nMaxBytes/2 ); |
|
nMaxBytes /= 2; |
|
if ( nMaxBytes < MINIMUM_WIN_MEMORY ) |
|
{ |
|
Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", MINIMUM_WIN_MEMORY/(1024*1024)); |
|
} |
|
} |
|
#else |
|
if ( !g_HunkMemoryStack.InitPhysical( 16*1024*1024 ) || !g_HunkOverflow.Init( nMaxBytes - 16*1024*1024, nMinCommitBytes ) ) |
|
{ |
|
Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", nMaxBytes ); |
|
} |
|
|
|
#endif |
|
g_pDataCache->SetSize( GetTargetCacheSize() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void Memory_Shutdown( void ) |
|
{ |
|
g_HunkMemoryStack.FreeAll(); |
|
|
|
// This disconnects the engine data cache |
|
g_pDataCache->SetSize( 0 ); |
|
}
|
|
|