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.
297 lines
6.4 KiB
297 lines
6.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#if defined( _WIN32 ) && !defined( _X360 ) |
|
#define WIN_32_LEAN_AND_MEAN |
|
#include <windows.h> |
|
#define VA_COMMIT_FLAGS MEM_COMMIT |
|
#define VA_RESERVE_FLAGS MEM_RESERVE |
|
#elif defined( _X360 ) |
|
#define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES) |
|
#define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES) |
|
#endif |
|
|
|
#include "tier0/dbg.h" |
|
#include "memstack.h" |
|
#include "utlmap.h" |
|
#include "tier0/memdbgon.h" |
|
|
|
#ifdef _WIN32 |
|
#pragma warning(disable:4073) |
|
#pragma init_seg(lib) |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack); |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
CMemoryStack::CMemoryStack() |
|
: m_pBase( NULL ), |
|
m_pNextAlloc( NULL ), |
|
m_pAllocLimit( NULL ), |
|
m_pCommitLimit( NULL ), |
|
m_alignment( 16 ), |
|
#if defined(_WIN32) |
|
m_commitSize( 0 ), |
|
m_minCommit( 0 ), |
|
#endif |
|
m_maxSize( 0 ) |
|
{ |
|
} |
|
|
|
//------------------------------------- |
|
|
|
CMemoryStack::~CMemoryStack() |
|
{ |
|
if ( m_pBase ) |
|
Term(); |
|
} |
|
|
|
//------------------------------------- |
|
|
|
bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment ) |
|
{ |
|
Assert( !m_pBase ); |
|
|
|
#ifdef _X360 |
|
m_bPhysical = false; |
|
#endif |
|
|
|
m_maxSize = maxSize; |
|
m_alignment = AlignValue( alignment, 4 ); |
|
|
|
Assert( m_alignment == alignment ); |
|
Assert( m_maxSize > 0 ); |
|
|
|
#if defined(_WIN32) |
|
if ( commitSize != 0 ) |
|
{ |
|
m_commitSize = commitSize; |
|
} |
|
|
|
unsigned pageSize; |
|
|
|
#ifndef _X360 |
|
SYSTEM_INFO sysInfo; |
|
GetSystemInfo( &sysInfo ); |
|
Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) ); |
|
pageSize = sysInfo.dwPageSize; |
|
#else |
|
pageSize = 64*1024; |
|
#endif |
|
|
|
if ( m_commitSize == 0 ) |
|
{ |
|
m_commitSize = pageSize; |
|
} |
|
else |
|
{ |
|
m_commitSize = AlignValue( m_commitSize, pageSize ); |
|
} |
|
|
|
m_maxSize = AlignValue( m_maxSize, m_commitSize ); |
|
|
|
Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize ); |
|
|
|
m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS ); |
|
Assert( m_pBase ); |
|
m_pCommitLimit = m_pNextAlloc = m_pBase; |
|
|
|
if ( initialCommit ) |
|
{ |
|
initialCommit = AlignValue( initialCommit, m_commitSize ); |
|
Assert( initialCommit < m_maxSize ); |
|
if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) ) |
|
return false; |
|
m_minCommit = initialCommit; |
|
m_pCommitLimit += initialCommit; |
|
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); |
|
} |
|
|
|
#else |
|
m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 ); |
|
m_pNextAlloc = m_pBase; |
|
m_pCommitLimit = m_pBase + m_maxSize; |
|
#endif |
|
|
|
m_pAllocLimit = m_pBase + m_maxSize; |
|
|
|
return ( m_pBase != NULL ); |
|
} |
|
|
|
//------------------------------------- |
|
|
|
#ifdef _X360 |
|
bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment ) |
|
{ |
|
m_bPhysical = true; |
|
|
|
m_maxSize = m_commitSize = size; |
|
m_alignment = AlignValue( alignment, 4 ); |
|
|
|
int flags = PAGE_READWRITE; |
|
if ( size >= 16*1024*1024 ) |
|
{ |
|
flags |= MEM_16MB_PAGES; |
|
} |
|
else |
|
{ |
|
flags |= MEM_LARGE_PAGES; |
|
} |
|
m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags ); |
|
Assert( m_pBase ); |
|
m_pNextAlloc = m_pBase; |
|
m_pCommitLimit = m_pBase + m_maxSize; |
|
m_pAllocLimit = m_pBase + m_maxSize; |
|
|
|
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); |
|
return ( m_pBase != NULL ); |
|
} |
|
#endif |
|
|
|
//------------------------------------- |
|
|
|
void CMemoryStack::Term() |
|
{ |
|
FreeAll(); |
|
if ( m_pBase ) |
|
{ |
|
#if defined(_WIN32) |
|
VirtualFree( m_pBase, 0, MEM_RELEASE ); |
|
#else |
|
MemAlloc_FreeAligned( m_pBase ); |
|
#endif |
|
m_pBase = NULL; |
|
} |
|
} |
|
|
|
//------------------------------------- |
|
|
|
int CMemoryStack::GetSize() |
|
{ |
|
#ifdef _WIN32 |
|
return m_pCommitLimit - m_pBase; |
|
#else |
|
return m_maxSize; |
|
#endif |
|
} |
|
|
|
|
|
//------------------------------------- |
|
|
|
bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT |
|
{ |
|
#ifdef _X360 |
|
if ( m_bPhysical ) |
|
{ |
|
return NULL; |
|
} |
|
#endif |
|
#if defined(_WIN32) |
|
unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize ); |
|
unsigned commitSize = pNewCommitLimit - m_pCommitLimit; |
|
|
|
if ( GetSize() ) |
|
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); |
|
|
|
if( m_pCommitLimit + commitSize > m_pAllocLimit ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) ) |
|
{ |
|
Assert( 0 ); |
|
return false; |
|
} |
|
m_pCommitLimit = pNewCommitLimit; |
|
|
|
if ( GetSize() ) |
|
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); |
|
return true; |
|
#else |
|
Assert( 0 ); |
|
return false; |
|
#endif |
|
} |
|
|
|
//------------------------------------- |
|
|
|
void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit ) |
|
{ |
|
void *pAllocPoint = m_pBase + mark; |
|
Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc ); |
|
|
|
if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc ) |
|
{ |
|
if ( bDecommit ) |
|
{ |
|
#if defined(_WIN32) |
|
unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize ); |
|
|
|
if ( pDecommitPoint < m_pBase + m_minCommit ) |
|
{ |
|
pDecommitPoint = m_pBase + m_minCommit; |
|
} |
|
|
|
unsigned decommitSize = m_pCommitLimit - pDecommitPoint; |
|
|
|
if ( decommitSize > 0 ) |
|
{ |
|
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); |
|
|
|
VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT ); |
|
m_pCommitLimit = pDecommitPoint; |
|
|
|
if ( mark > 0 ) |
|
{ |
|
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() ); |
|
} |
|
} |
|
#endif |
|
} |
|
m_pNextAlloc = (unsigned char *)pAllocPoint; |
|
} |
|
} |
|
|
|
//------------------------------------- |
|
|
|
void CMemoryStack::FreeAll( bool bDecommit ) |
|
{ |
|
if ( m_pBase && m_pCommitLimit - m_pBase > 0 ) |
|
{ |
|
if ( bDecommit ) |
|
{ |
|
#if defined(_WIN32) |
|
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() ); |
|
|
|
VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT ); |
|
m_pCommitLimit = m_pBase; |
|
#endif |
|
} |
|
m_pNextAlloc = m_pBase; |
|
} |
|
} |
|
|
|
//------------------------------------- |
|
|
|
void CMemoryStack::Access( void **ppRegion, unsigned *pBytes ) |
|
{ |
|
*ppRegion = m_pBase; |
|
*pBytes = ( m_pNextAlloc - m_pBase); |
|
} |
|
|
|
//------------------------------------- |
|
|
|
void CMemoryStack::PrintContents() |
|
{ |
|
Msg( "Total used memory: %d\n", GetUsed() ); |
|
Msg( "Total committed memory: %d\n", GetSize() ); |
|
} |
|
|
|
//-----------------------------------------------------------------------------
|
|
|