2022-11-29 00:01:47 +01:00
|
|
|
|
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======//
|
|
|
|
|
//
|
|
|
|
|
// Purpose:
|
|
|
|
|
//
|
|
|
|
|
//=============================================================================//
|
|
|
|
|
|
|
|
|
|
#include "tier0/dbg.h"
|
|
|
|
|
#include "tier0/memstd.h"
|
2023-05-10 00:05:38 +02:00
|
|
|
|
#include "tier1/memstack.h"
|
|
|
|
|
#include "tier1/utlmap.h"
|
|
|
|
|
#include "tier0/memdbgon.h"
|
2022-11-29 00:01:47 +01:00
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#pragma warning(disable:4073)
|
|
|
|
|
#pragma init_seg(lib)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define VA_COMMIT_FLAGS MEM_COMMIT
|
|
|
|
|
#define VA_RESERVE_FLAGS MEM_RESERVE
|
|
|
|
|
|
|
|
|
|
static volatile bool bSpewAllocations = false; // TODO: Register CMemoryStacks with g_pMemAlloc, so it can spew a summary
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void PrintStatus( void* p )
|
|
|
|
|
{
|
|
|
|
|
CMemoryStack* pMemoryStack = (CMemoryStack*)p;
|
|
|
|
|
|
|
|
|
|
pMemoryStack->PrintContents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMemoryStack::CMemoryStack()
|
2022-11-29 01:45:24 +01:00
|
|
|
|
: m_pNextAlloc( nullptr )
|
|
|
|
|
, m_pCommitLimit( nullptr )
|
|
|
|
|
, m_pAllocLimit( nullptr )
|
|
|
|
|
, m_pHighestAllocLimit( nullptr )
|
|
|
|
|
, m_pBase( nullptr )
|
|
|
|
|
, m_pUnkPtr( nullptr )
|
2022-11-29 00:01:47 +01:00
|
|
|
|
, m_bRegisteredAllocation( false )
|
2022-11-29 01:45:24 +01:00
|
|
|
|
, m_unkSize( 0 )
|
2022-11-29 00:01:47 +01:00
|
|
|
|
, m_maxSize( 0 )
|
|
|
|
|
, m_alignment( 16 )
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
, m_commitIncrement( 0 )
|
|
|
|
|
, m_minCommit( 0 )
|
|
|
|
|
#ifdef _PS3
|
|
|
|
|
, m_pVirtualMemorySection( NULL )
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
{
|
2022-11-29 01:45:24 +01:00
|
|
|
|
//AddMemoryInfoCallback( this );
|
2022-11-29 00:01:47 +01:00
|
|
|
|
m_pszAllocOwner = strdup( "CMemoryStack unattributed" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
CMemoryStack::~CMemoryStack()
|
|
|
|
|
{
|
|
|
|
|
if ( m_pBase )
|
|
|
|
|
Term();
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
//RemoveMemoryInfoCallback( this );
|
2022-11-29 00:01:47 +01:00
|
|
|
|
free( m_pszAllocOwner );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
bool CMemoryStack::Init( const char *pszAllocOwner, uint64 maxSize, uint64 commitIncrement, uint64 initialCommit, uint64 alignment )
|
2022-11-29 00:01:47 +01:00
|
|
|
|
{
|
|
|
|
|
Assert( !m_pBase );
|
|
|
|
|
|
|
|
|
|
m_bPhysical = false;
|
|
|
|
|
|
|
|
|
|
m_maxSize = maxSize;
|
|
|
|
|
m_alignment = AlignValue( alignment, 4 );
|
|
|
|
|
|
|
|
|
|
Assert( m_alignment == alignment );
|
|
|
|
|
Assert( m_maxSize > 0 );
|
|
|
|
|
|
|
|
|
|
SetAllocOwner( pszAllocOwner );
|
|
|
|
|
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
|
|
|
|
|
#ifdef _PS3
|
|
|
|
|
// Memory can only be committed in page-size increments on PS3
|
|
|
|
|
static const unsigned PS3_PAGE_SIZE = 64*1024;
|
|
|
|
|
if ( commitSize < PS3_PAGE_SIZE )
|
|
|
|
|
commitSize = PS3_PAGE_SIZE;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( commitIncrement != 0 )
|
|
|
|
|
{
|
|
|
|
|
m_commitIncrement = commitIncrement;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
uint64 pageSize;
|
2022-11-29 00:01:47 +01:00
|
|
|
|
|
|
|
|
|
#ifdef _PS3
|
|
|
|
|
pageSize = PS3_PAGE_SIZE;
|
|
|
|
|
#elif defined( _X360 )
|
|
|
|
|
pageSize = 64 * 1024;
|
|
|
|
|
#else
|
|
|
|
|
SYSTEM_INFO sysInfo;
|
|
|
|
|
GetSystemInfo( &sysInfo );
|
|
|
|
|
Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
|
|
|
|
|
pageSize = sysInfo.dwPageSize;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( m_commitIncrement == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_commitIncrement = pageSize;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_commitIncrement = AlignValue( m_commitIncrement, pageSize );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_maxSize = AlignValue( m_maxSize, m_commitIncrement );
|
|
|
|
|
|
|
|
|
|
Assert( m_maxSize % pageSize == 0 && m_commitIncrement % pageSize == 0 && m_commitIncrement <= m_maxSize );
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
|
|
|
|
|
#else
|
|
|
|
|
m_pVirtualMemorySection = g_pMemAlloc->AllocateVirtualMemorySection( m_maxSize );
|
|
|
|
|
if ( !m_pVirtualMemorySection )
|
|
|
|
|
{
|
|
|
|
|
Warning( "AllocateVirtualMemorySection failed( size=%d )\n", m_maxSize );
|
|
|
|
|
Assert( 0 );
|
|
|
|
|
m_pBase = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pBase = ( byte* ) m_pVirtualMemorySection->GetBaseAddress();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if ( !m_pBase )
|
|
|
|
|
{
|
|
|
|
|
#if !defined( NO_MALLOC_OVERRIDE )
|
|
|
|
|
g_pMemAlloc->OutOfMemory();
|
|
|
|
|
#endif
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_pCommitLimit = m_pNextAlloc = m_pBase;
|
|
|
|
|
|
|
|
|
|
if ( initialCommit )
|
|
|
|
|
{
|
|
|
|
|
initialCommit = AlignValue( initialCommit, m_commitIncrement );
|
|
|
|
|
Assert( initialCommit <= m_maxSize );
|
|
|
|
|
bool bInitialCommitSucceeded = false;
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
bInitialCommitSucceeded = !!VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE );
|
|
|
|
|
#else
|
|
|
|
|
m_pVirtualMemorySection->CommitPages( m_pCommitLimit, initialCommit );
|
|
|
|
|
bInitialCommitSucceeded = true;
|
|
|
|
|
#endif
|
|
|
|
|
if ( !bInitialCommitSucceeded )
|
|
|
|
|
{
|
|
|
|
|
#if !defined( NO_MALLOC_OVERRIDE )
|
|
|
|
|
g_pMemAlloc->OutOfMemory( initialCommit );
|
|
|
|
|
#endif
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_minCommit = initialCommit;
|
|
|
|
|
m_pCommitLimit += initialCommit;
|
|
|
|
|
RegisterAllocation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
m_pBase = (byte*)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
|
|
|
|
|
m_pNextAlloc = m_pBase;
|
|
|
|
|
m_pCommitLimit = m_pBase + m_maxSize;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
m_pHighestAllocLimit = m_pNextAlloc;
|
|
|
|
|
|
|
|
|
|
m_pAllocLimit = m_pBase + m_maxSize;
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
return ( m_pBase != nullptr );
|
2022-11-29 00:01:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifdef _GAMECONSOLE
|
|
|
|
|
bool CMemoryStack::InitPhysical( const char *pszAllocOwner, uint size, uint nBaseAddrAlignment, uint alignment, uint32 nFlags )
|
|
|
|
|
{
|
|
|
|
|
m_bPhysical = true;
|
|
|
|
|
|
|
|
|
|
m_maxSize = m_commitIncrement = size;
|
|
|
|
|
m_alignment = AlignValue( alignment, 4 );
|
|
|
|
|
|
|
|
|
|
SetAllocOwner( pszAllocOwner );
|
|
|
|
|
|
|
|
|
|
#ifdef _X360
|
|
|
|
|
int flags = PAGE_READWRITE | nFlags;
|
|
|
|
|
if ( size >= 16*1024*1024 )
|
|
|
|
|
{
|
|
|
|
|
flags |= MEM_16MB_PAGES;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
flags |= MEM_LARGE_PAGES;
|
|
|
|
|
}
|
|
|
|
|
m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, nBaseAddrAlignment, flags );
|
|
|
|
|
#elif defined (_PS3)
|
|
|
|
|
m_pBase = (byte*)nFlags;
|
|
|
|
|
m_pBase = (byte*)AlignValue( (uintp)m_pBase, m_alignment );
|
|
|
|
|
#else
|
|
|
|
|
#pragma error
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
Assert( m_pBase );
|
|
|
|
|
m_pNextAlloc = m_pBase;
|
|
|
|
|
m_pCommitLimit = m_pBase + m_maxSize;
|
|
|
|
|
m_pAllocLimit = m_pBase + m_maxSize;
|
|
|
|
|
m_pHighestAllocLimit = m_pNextAlloc;
|
|
|
|
|
|
|
|
|
|
RegisterAllocation();
|
|
|
|
|
return ( m_pBase != NULL );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
void CMemoryStack::Term()
|
|
|
|
|
{
|
|
|
|
|
FreeAll();
|
|
|
|
|
if ( m_pBase )
|
|
|
|
|
{
|
|
|
|
|
#ifdef _GAMECONSOLE
|
|
|
|
|
if ( m_bPhysical )
|
|
|
|
|
{
|
|
|
|
|
#if defined( _X360 )
|
|
|
|
|
XPhysicalFree( m_pBase );
|
|
|
|
|
#elif defined( _PS3 )
|
|
|
|
|
#else
|
|
|
|
|
#pragma error
|
|
|
|
|
#endif
|
|
|
|
|
m_pCommitLimit = m_pBase = NULL;
|
|
|
|
|
m_maxSize = 0;
|
|
|
|
|
RegisterDeallocation(true);
|
|
|
|
|
m_bPhysical = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif // _GAMECONSOLE
|
|
|
|
|
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
VirtualFree( m_pBase, 0, MEM_RELEASE );
|
|
|
|
|
#else
|
|
|
|
|
m_pVirtualMemorySection->Release();
|
|
|
|
|
m_pVirtualMemorySection = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
MemAlloc_FreeAligned( m_pBase );
|
|
|
|
|
#endif
|
2022-11-29 01:45:24 +01:00
|
|
|
|
m_pBase = nullptr;
|
2022-11-29 00:01:47 +01:00
|
|
|
|
// Zero these variables to avoid getting misleading mem_dump
|
|
|
|
|
// results when m_pBase is NULL.
|
2022-11-29 01:45:24 +01:00
|
|
|
|
m_pNextAlloc = nullptr;
|
|
|
|
|
m_pCommitLimit = nullptr;
|
|
|
|
|
m_pHighestAllocLimit = nullptr;
|
|
|
|
|
m_pUnkPtr = nullptr;
|
2022-11-29 00:01:47 +01:00
|
|
|
|
m_maxSize = 0;
|
|
|
|
|
RegisterDeallocation(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
uint64 CMemoryStack::GetSize() const
|
2022-11-29 00:01:47 +01:00
|
|
|
|
{
|
|
|
|
|
if ( m_bPhysical )
|
|
|
|
|
return m_maxSize;
|
|
|
|
|
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
return m_pCommitLimit - m_pBase;
|
|
|
|
|
#else
|
|
|
|
|
return m_maxSize;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
|
|
|
|
|
{
|
|
|
|
|
if ( m_bPhysical )
|
|
|
|
|
{
|
2022-11-29 01:45:24 +01:00
|
|
|
|
return false;
|
2022-11-29 00:01:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitIncrement );
|
|
|
|
|
ptrdiff_t commitIncrement = pNewCommitLimit - m_pCommitLimit;
|
|
|
|
|
|
|
|
|
|
if( m_pCommitLimit + commitIncrement > m_pAllocLimit )
|
|
|
|
|
{
|
|
|
|
|
#if !defined( NO_MALLOC_OVERRIDE )
|
|
|
|
|
g_pMemAlloc->OutOfMemory( commitIncrement );
|
|
|
|
|
#endif
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pNewCommitLimit > m_pCommitLimit )
|
|
|
|
|
{
|
|
|
|
|
RegisterDeallocation(false);
|
|
|
|
|
bool bAllocationSucceeded = false;
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
bAllocationSucceeded = !!VirtualAlloc( m_pCommitLimit, commitIncrement, VA_COMMIT_FLAGS, PAGE_READWRITE );
|
|
|
|
|
#else
|
|
|
|
|
bAllocationSucceeded = m_pVirtualMemorySection->CommitPages( m_pCommitLimit, commitIncrement );
|
|
|
|
|
#endif
|
|
|
|
|
if ( !bAllocationSucceeded )
|
|
|
|
|
{
|
|
|
|
|
#if !defined( NO_MALLOC_OVERRIDE )
|
|
|
|
|
g_pMemAlloc->OutOfMemory( commitIncrement );
|
|
|
|
|
#endif
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_pCommitLimit = pNewCommitLimit;
|
|
|
|
|
|
|
|
|
|
RegisterAllocation();
|
|
|
|
|
}
|
|
|
|
|
else if ( pNewCommitLimit < m_pCommitLimit )
|
|
|
|
|
{
|
|
|
|
|
if ( m_pNextAlloc > pNewCommitLimit )
|
|
|
|
|
{
|
|
|
|
|
Warning( eDLL_T::COMMON, "ATTEMPTED TO DECOMMIT OWNED MEMORY STACK SPACE\n" );
|
|
|
|
|
pNewCommitLimit = AlignValue( m_pNextAlloc, m_commitIncrement );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pNewCommitLimit < m_pCommitLimit )
|
|
|
|
|
{
|
|
|
|
|
RegisterDeallocation(false);
|
|
|
|
|
ptrdiff_t decommitIncrement = m_pCommitLimit - pNewCommitLimit;
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
VirtualFree( pNewCommitLimit, decommitIncrement, MEM_DECOMMIT );
|
|
|
|
|
#else
|
|
|
|
|
m_pVirtualMemorySection->DecommitPages( pNewCommitLimit, decommitIncrement );
|
|
|
|
|
#endif
|
|
|
|
|
m_pCommitLimit = pNewCommitLimit;
|
|
|
|
|
RegisterAllocation();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Identify the owner of this memory stack's memory
|
|
|
|
|
void CMemoryStack::SetAllocOwner( const char *pszAllocOwner )
|
|
|
|
|
{
|
|
|
|
|
if ( !pszAllocOwner || !Q_strcmp( m_pszAllocOwner, pszAllocOwner ) )
|
|
|
|
|
return;
|
|
|
|
|
free( m_pszAllocOwner );
|
|
|
|
|
m_pszAllocOwner = strdup( pszAllocOwner );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMemoryStack::RegisterAllocation()
|
|
|
|
|
{
|
|
|
|
|
// 'physical' allocations on PS3 come from RSX local memory, so we don't count them here:
|
|
|
|
|
if ( IsPS3() && m_bPhysical )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if ( GetSize() )
|
|
|
|
|
{
|
|
|
|
|
if ( m_bRegisteredAllocation )
|
|
|
|
|
Warning( eDLL_T::COMMON, "CMemoryStack: ERROR - mismatched RegisterAllocation/RegisterDeallocation!\n" );
|
|
|
|
|
|
|
|
|
|
// NOTE: we deliberately don't use MemAlloc_RegisterExternalAllocation. CMemoryStack needs to bypass 'GetActualDbgInfo'
|
|
|
|
|
// due to the way it allocates memory: there's just one representative memory address (m_pBase), it grows at unpredictable
|
|
|
|
|
// times (in CommitTo, not every Alloc call) and it is freed en-masse (instead of freeing each individual allocation).
|
|
|
|
|
MemAlloc_RegisterAllocation( m_pszAllocOwner, 0, GetSize(), GetSize(), 0 );
|
|
|
|
|
}
|
|
|
|
|
m_bRegisteredAllocation = true;
|
|
|
|
|
|
|
|
|
|
// Temp memorystack spew: very useful when we crash out of memory
|
|
|
|
|
if ( IsGameConsole() && bSpewAllocations ) DevMsg( eDLL_T::COMMON, "CMemoryStack: %4.1fMB (%s)\n", GetSize()/(float)(1024*1024), m_pszAllocOwner );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMemoryStack::RegisterDeallocation( bool bShouldSpewSize )
|
|
|
|
|
{
|
|
|
|
|
// 'physical' allocations on PS3 come from RSX local memory, so we don't count them here:
|
|
|
|
|
if ( IsPS3() && m_bPhysical )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if ( GetSize() )
|
|
|
|
|
{
|
|
|
|
|
if ( !m_bRegisteredAllocation )
|
|
|
|
|
Warning( eDLL_T::COMMON, "CMemoryStack: ERROR - mismatched RegisterAllocation/RegisterDeallocation!\n" );
|
|
|
|
|
MemAlloc_RegisterDeallocation( m_pszAllocOwner, 0, GetSize(), GetSize(), 0 );
|
|
|
|
|
}
|
|
|
|
|
m_bRegisteredAllocation = false;
|
|
|
|
|
|
|
|
|
|
// Temp memorystack spew: very useful when we crash out of memory
|
|
|
|
|
if ( bShouldSpewSize && IsGameConsole() && bSpewAllocations ) DevMsg( eDLL_T::COMMON, "CMemoryStack: %4.1fMB (%s)\n", GetSize()/(float)(1024*1024), m_pszAllocOwner );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
|
|
|
|
|
{
|
|
|
|
|
mark = AlignValue( mark, m_alignment );
|
|
|
|
|
byte *pAllocPoint = m_pBase + mark;
|
|
|
|
|
|
|
|
|
|
Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
|
|
|
|
|
if ( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc )
|
|
|
|
|
{
|
|
|
|
|
m_pNextAlloc = pAllocPoint;
|
|
|
|
|
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
|
|
|
|
if ( bDecommit && !m_bPhysical )
|
|
|
|
|
{
|
|
|
|
|
CommitTo( MAX( m_pNextAlloc, (m_pBase + m_minCommit) ) );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
|
|
|
|
void CMemoryStack::FreeAll( bool bDecommit )
|
|
|
|
|
{
|
|
|
|
|
if ( m_pBase && ( m_pBase < m_pCommitLimit ) )
|
|
|
|
|
{
|
|
|
|
|
FreeToAllocPoint( 0, bDecommit );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
void CMemoryStack::Access( void **ppRegion, uint64 *pBytes )
|
2022-11-29 00:01:47 +01:00
|
|
|
|
{
|
|
|
|
|
*ppRegion = m_pBase;
|
|
|
|
|
*pBytes = ( m_pNextAlloc - m_pBase);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
//const char* CMemoryStack::GetMemoryName() const
|
|
|
|
|
//{
|
|
|
|
|
// return m_pszAllocOwner;
|
|
|
|
|
//}
|
|
|
|
|
//
|
|
|
|
|
//size_t CMemoryStack::GetAllocatedBytes() const
|
|
|
|
|
//{
|
|
|
|
|
// return GetUsed();
|
|
|
|
|
//}
|
|
|
|
|
//
|
|
|
|
|
//size_t CMemoryStack::GetCommittedBytes() const
|
|
|
|
|
//{
|
|
|
|
|
// return GetSize();
|
|
|
|
|
//}
|
|
|
|
|
//
|
|
|
|
|
//size_t CMemoryStack::GetReservedBytes() const
|
|
|
|
|
//{
|
|
|
|
|
// return GetMaxSize();
|
|
|
|
|
//}
|
2022-11-29 00:01:47 +01:00
|
|
|
|
|
|
|
|
|
//size_t CMemoryStack::GetHighestBytes() const
|
|
|
|
|
//{
|
|
|
|
|
// size_t highest = m_pHighestAllocLimit - m_pBase;
|
|
|
|
|
// return highest;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
|
|
2022-11-29 01:45:24 +01:00
|
|
|
|
void CMemoryStack::PrintContents() const
|
|
|
|
|
{
|
|
|
|
|
size_t highest = m_pHighestAllocLimit - m_pBase;
|
|
|
|
|
MEMORY_BASIC_INFORMATION info;
|
|
|
|
|
char moduleName[260];
|
|
|
|
|
strcpy( moduleName, "unknown module" );
|
|
|
|
|
// Because this code is statically linked into each DLL, this function and the PrintStatus
|
|
|
|
|
// function will be in the DLL that constructed the CMemoryStack object. We can then
|
|
|
|
|
// retrieve the DLL name to give slightly more verbose memory dumps.
|
|
|
|
|
if ( VirtualQuery( &PrintStatus, &info, sizeof( info ) ) == sizeof( info ) )
|
|
|
|
|
{
|
|
|
|
|
GetModuleFileNameA( (HMODULE) info.AllocationBase, moduleName, _countof( moduleName ) );
|
|
|
|
|
moduleName[ _countof( moduleName )-1 ] = 0;
|
|
|
|
|
}
|
|
|
|
|
DevMsg( eDLL_T::COMMON, "CMemoryStack %s in %s\n", m_pszAllocOwner, moduleName );
|
|
|
|
|
DevMsg( eDLL_T::COMMON, " Total used memory: %zu KB\n", GetUsed() / 1024 );
|
|
|
|
|
DevMsg( eDLL_T::COMMON, " Total committed memory: %zu KB\n", GetSize() / 1024 );
|
|
|
|
|
DevMsg( eDLL_T::COMMON, " Max committed memory: %zu KB out of %zu KB\n", highest / 1024, GetMaxSize() / 1024 );
|
|
|
|
|
}
|