Team Fortress 2 Source Code as on 22/4/2020
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.

641 lines
18 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #if defined( _WIN32 ) && !defined( _X360 )
  7. #define WIN_32_LEAN_AND_MEAN
  8. #include <windows.h>
  9. #define VA_COMMIT_FLAGS MEM_COMMIT
  10. #define VA_RESERVE_FLAGS MEM_RESERVE
  11. #elif defined( _X360 )
  12. #define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES)
  13. #define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES)
  14. #elif defined( _PS3 )
  15. #include "sys/memory.h"
  16. #include "sys/mempool.h"
  17. #include "sys/process.h"
  18. #include <sys/vm.h>
  19. #endif
  20. #include "tier0/dbg.h"
  21. #include "memstack.h"
  22. #include "utlmap.h"
  23. #include "tier0/memdbgon.h"
  24. #ifdef _WIN32
  25. #pragma warning(disable:4073)
  26. #pragma init_seg(lib)
  27. #endif
  28. static volatile bool bSpewAllocations = false; // TODO: Register CMemoryStacks with g_pMemAlloc, so it can spew a summary
  29. //-----------------------------------------------------------------------------
  30. MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
  31. //-----------------------------------------------------------------------------
  32. CMemoryStack::CMemoryStack()
  33. : m_pBase( NULL ),
  34. m_pNextAlloc( NULL ),
  35. m_pAllocLimit( NULL ),
  36. m_pCommitLimit( NULL ),
  37. m_alignment( 16 ),
  38. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  39. m_commitSize( 0 ),
  40. m_minCommit( 0 ),
  41. #ifdef _PS3
  42. m_pVirtualMemorySection( NULL ),
  43. #endif
  44. #endif
  45. m_maxSize( 0 ),
  46. m_bRegisteredAllocation( false )
  47. {
  48. m_pszAllocOwner = strdup( "CMemoryStack unattributed" );
  49. }
  50. //-------------------------------------
  51. CMemoryStack::~CMemoryStack()
  52. {
  53. if ( m_pBase )
  54. Term();
  55. free( m_pszAllocOwner );
  56. }
  57. //-------------------------------------
  58. bool CMemoryStack::Init( const char *pszAllocOwner, unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment )
  59. {
  60. Assert( !m_pBase );
  61. m_bPhysical = false;
  62. m_maxSize = maxSize;
  63. m_alignment = AlignValue( alignment, 4 );
  64. Assert( m_alignment == alignment );
  65. Assert( m_maxSize > 0 );
  66. SetAllocOwner( pszAllocOwner );
  67. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  68. #ifdef _PS3
  69. // Memory can only be committed in page-size increments on PS3
  70. static const unsigned PS3_PAGE_SIZE = 64*1024;
  71. if ( commitSize < PS3_PAGE_SIZE )
  72. commitSize = PS3_PAGE_SIZE;
  73. #endif
  74. if ( commitSize != 0 )
  75. {
  76. m_commitSize = commitSize;
  77. }
  78. unsigned pageSize;
  79. #ifdef _PS3
  80. pageSize = PS3_PAGE_SIZE;
  81. #elif defined( _X360 )
  82. pageSize = 64 * 1024;
  83. #else
  84. SYSTEM_INFO sysInfo;
  85. GetSystemInfo( &sysInfo );
  86. Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
  87. pageSize = sysInfo.dwPageSize;
  88. #endif
  89. if ( m_commitSize == 0 )
  90. {
  91. m_commitSize = pageSize;
  92. }
  93. else
  94. {
  95. m_commitSize = AlignValue( m_commitSize, pageSize );
  96. }
  97. m_maxSize = AlignValue( m_maxSize, m_commitSize );
  98. Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize );
  99. #ifdef _WIN32
  100. m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
  101. #else
  102. m_pVirtualMemorySection = g_pMemAlloc->AllocateVirtualMemorySection( m_maxSize );
  103. if ( !m_pVirtualMemorySection )
  104. {
  105. Warning( "AllocateVirtualMemorySection failed( size=%d )\n", m_maxSize );
  106. Assert( 0 );
  107. m_pBase = NULL;
  108. }
  109. else
  110. {
  111. m_pBase = ( byte* ) m_pVirtualMemorySection->GetBaseAddress();
  112. }
  113. #endif
  114. if ( !m_pBase )
  115. {
  116. #if !defined( NO_MALLOC_OVERRIDE )
  117. g_pMemAlloc->OutOfMemory();
  118. #endif
  119. return false;
  120. }
  121. m_pCommitLimit = m_pNextAlloc = m_pBase;
  122. if ( initialCommit )
  123. {
  124. initialCommit = AlignValue( initialCommit, m_commitSize );
  125. Assert( initialCommit <= m_maxSize );
  126. bool bInitialCommitSucceeded = false;
  127. #ifdef _WIN32
  128. bInitialCommitSucceeded = !!VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE );
  129. #else
  130. m_pVirtualMemorySection->CommitPages( m_pCommitLimit, initialCommit );
  131. bInitialCommitSucceeded = true;
  132. #endif
  133. if ( !bInitialCommitSucceeded )
  134. {
  135. #if !defined( NO_MALLOC_OVERRIDE )
  136. g_pMemAlloc->OutOfMemory( initialCommit );
  137. #endif
  138. return false;
  139. }
  140. m_minCommit = initialCommit;
  141. m_pCommitLimit += initialCommit;
  142. RegisterAllocation();
  143. }
  144. #else
  145. m_pBase = (byte*)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
  146. m_pNextAlloc = m_pBase;
  147. m_pCommitLimit = m_pBase + m_maxSize;
  148. #endif
  149. m_pAllocLimit = m_pBase + m_maxSize;
  150. return ( m_pBase != NULL );
  151. }
  152. //-------------------------------------
  153. #ifdef _GAMECONSOLE
  154. bool CMemoryStack::InitPhysical( const char *pszAllocOwner, uint size, uint nBaseAddrAlignment, uint alignment, uint32 nFlags )
  155. {
  156. m_bPhysical = true;
  157. m_maxSize = m_commitSize = size;
  158. m_alignment = AlignValue( alignment, 4 );
  159. SetAllocOwner( pszAllocOwner );
  160. #ifdef _X360
  161. int flags = PAGE_READWRITE | nFlags;
  162. if ( size >= 16*1024*1024 )
  163. {
  164. flags |= MEM_16MB_PAGES;
  165. }
  166. else
  167. {
  168. flags |= MEM_LARGE_PAGES;
  169. }
  170. m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, nBaseAddrAlignment, flags );
  171. #elif defined (_PS3)
  172. m_pBase = (byte*)nFlags;
  173. m_pBase = (byte*)AlignValue( (uintp)m_pBase, m_alignment );
  174. #else
  175. #pragma error
  176. #endif
  177. Assert( m_pBase );
  178. m_pNextAlloc = m_pBase;
  179. m_pCommitLimit = m_pBase + m_maxSize;
  180. m_pAllocLimit = m_pBase + m_maxSize;
  181. RegisterAllocation();
  182. return ( m_pBase != NULL );
  183. }
  184. #endif
  185. //-------------------------------------
  186. void CMemoryStack::Term()
  187. {
  188. FreeAll();
  189. if ( m_pBase )
  190. {
  191. #ifdef _GAMECONSOLE
  192. if ( m_bPhysical )
  193. {
  194. #if defined( _X360 )
  195. XPhysicalFree( m_pBase );
  196. #elif defined( _PS3 )
  197. #else
  198. #pragma error
  199. #endif
  200. m_pCommitLimit = m_pBase = NULL;
  201. m_maxSize = 0;
  202. RegisterDeallocation(true);
  203. m_bPhysical = false;
  204. return;
  205. }
  206. #endif // _GAMECONSOLE
  207. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  208. #if defined(_WIN32)
  209. VirtualFree( m_pBase, 0, MEM_RELEASE );
  210. #else
  211. m_pVirtualMemorySection->Release();
  212. m_pVirtualMemorySection = NULL;
  213. #endif
  214. #else
  215. MemAlloc_FreeAligned( m_pBase );
  216. #endif
  217. m_pCommitLimit = m_pBase = NULL;
  218. m_maxSize = 0;
  219. RegisterDeallocation(true);
  220. }
  221. }
  222. //-------------------------------------
  223. int CMemoryStack::GetSize()
  224. {
  225. if ( m_bPhysical )
  226. return m_maxSize;
  227. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  228. return m_pCommitLimit - m_pBase;
  229. #else
  230. return m_maxSize;
  231. #endif
  232. }
  233. //-------------------------------------
  234. bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
  235. {
  236. if ( m_bPhysical )
  237. {
  238. return NULL;
  239. }
  240. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  241. unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize );
  242. ptrdiff_t commitSize = pNewCommitLimit - m_pCommitLimit;
  243. if( m_pCommitLimit + commitSize > m_pAllocLimit )
  244. {
  245. return false;
  246. }
  247. if ( pNewCommitLimit > m_pCommitLimit )
  248. {
  249. RegisterDeallocation(false);
  250. bool bAllocationSucceeded = false;
  251. #ifdef _WIN32
  252. bAllocationSucceeded = !!VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE );
  253. #else
  254. bAllocationSucceeded = m_pVirtualMemorySection->CommitPages( m_pCommitLimit, commitSize );
  255. #endif
  256. if ( !bAllocationSucceeded )
  257. {
  258. #if !defined( NO_MALLOC_OVERRIDE )
  259. g_pMemAlloc->OutOfMemory( commitSize );
  260. #endif
  261. return false;
  262. }
  263. m_pCommitLimit = pNewCommitLimit;
  264. RegisterAllocation();
  265. }
  266. else if ( pNewCommitLimit < m_pCommitLimit )
  267. {
  268. if ( m_pNextAlloc > pNewCommitLimit )
  269. {
  270. Warning( "ATTEMPTED TO DECOMMIT OWNED MEMORY STACK SPACE\n" );
  271. pNewCommitLimit = AlignValue( m_pNextAlloc, m_commitSize );
  272. }
  273. if ( pNewCommitLimit < m_pCommitLimit )
  274. {
  275. RegisterDeallocation(false);
  276. ptrdiff_t decommitSize = m_pCommitLimit - pNewCommitLimit;
  277. #ifdef _WIN32
  278. VirtualFree( pNewCommitLimit, decommitSize, MEM_DECOMMIT );
  279. #else
  280. m_pVirtualMemorySection->DecommitPages( pNewCommitLimit, decommitSize );
  281. #endif
  282. m_pCommitLimit = pNewCommitLimit;
  283. RegisterAllocation();
  284. }
  285. }
  286. return true;
  287. #else
  288. return false;
  289. #endif
  290. }
  291. // Identify the owner of this memory stack's memory
  292. void CMemoryStack::SetAllocOwner( const char *pszAllocOwner )
  293. {
  294. if ( !pszAllocOwner || !V_strcmp( m_pszAllocOwner, pszAllocOwner ) )
  295. return;
  296. free( m_pszAllocOwner );
  297. m_pszAllocOwner = strdup( pszAllocOwner );
  298. }
  299. void CMemoryStack::RegisterAllocation()
  300. {
  301. // 'physical' allocations on PS3 come from RSX local memory, so we don't count them here:
  302. if ( IsPS3() && m_bPhysical )
  303. return;
  304. if ( GetSize() )
  305. {
  306. if ( m_bRegisteredAllocation )
  307. Warning( "CMemoryStack: ERROR - mismatched RegisterAllocation/RegisterDeallocation!\n" );
  308. // NOTE: we deliberately don't use MemAlloc_RegisterExternalAllocation. CMemoryStack needs to bypass 'GetActualDbgInfo'
  309. // due to the way it allocates memory: there's just one representative memory address (m_pBase), it grows at unpredictable
  310. // times (in CommitTo, not every Alloc call) and it is freed en-masse (instead of freeing each individual allocation).
  311. MemAlloc_RegisterAllocation( m_pszAllocOwner, 0, GetSize(), GetSize(), 0 );
  312. }
  313. m_bRegisteredAllocation = true;
  314. // Temp memorystack spew: very useful when we crash out of memory
  315. if ( IsGameConsole() && bSpewAllocations ) Msg( "CMemoryStack: %4.1fMB (%s)\n", GetSize()/(float)(1024*1024), m_pszAllocOwner );
  316. }
  317. void CMemoryStack::RegisterDeallocation( bool bShouldSpewSize )
  318. {
  319. // 'physical' allocations on PS3 come from RSX local memory, so we don't count them here:
  320. if ( IsPS3() && m_bPhysical )
  321. return;
  322. if ( GetSize() )
  323. {
  324. if ( !m_bRegisteredAllocation )
  325. Warning( "CMemoryStack: ERROR - mismatched RegisterAllocation/RegisterDeallocation!\n" );
  326. MemAlloc_RegisterDeallocation( m_pszAllocOwner, 0, GetSize(), GetSize(), 0 );
  327. }
  328. m_bRegisteredAllocation = false;
  329. // Temp memorystack spew: very useful when we crash out of memory
  330. if ( bShouldSpewSize && IsGameConsole() && bSpewAllocations ) Msg( "CMemoryStack: %4.1fMB (%s)\n", GetSize()/(float)(1024*1024), m_pszAllocOwner );
  331. }
  332. //-------------------------------------
  333. void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
  334. {
  335. mark = AlignValue( mark, m_alignment );
  336. byte *pAllocPoint = m_pBase + mark;
  337. Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
  338. if ( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc )
  339. {
  340. m_pNextAlloc = pAllocPoint;
  341. #ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
  342. if ( bDecommit && !m_bPhysical )
  343. {
  344. CommitTo( MAX( m_pNextAlloc, (m_pBase + m_minCommit) ) );
  345. }
  346. #endif
  347. }
  348. }
  349. //-------------------------------------
  350. void CMemoryStack::FreeAll( bool bDecommit )
  351. {
  352. if ( m_pBase && ( m_pBase < m_pCommitLimit ) )
  353. {
  354. FreeToAllocPoint( 0, bDecommit );
  355. }
  356. }
  357. //-------------------------------------
  358. void CMemoryStack::Access( void **ppRegion, unsigned *pBytes )
  359. {
  360. *ppRegion = m_pBase;
  361. *pBytes = ( m_pNextAlloc - m_pBase);
  362. }
  363. //-------------------------------------
  364. void CMemoryStack::PrintContents()
  365. {
  366. Msg( "Total used memory: %d\n", GetUsed() );
  367. Msg( "Total committed memory: %d\n", GetSize() );
  368. }
  369. #ifdef _X360
  370. //-----------------------------------------------------------------------------
  371. //
  372. // A memory stack used for allocating physical memory on the 360 (can't commit/decommit)
  373. //
  374. //-----------------------------------------------------------------------------
  375. MEMALLOC_DEFINE_EXTERNAL_TRACKING(CPhysicalMemoryStack);
  376. //-----------------------------------------------------------------------------
  377. // Constructor, destructor
  378. //-----------------------------------------------------------------------------
  379. CPhysicalMemoryStack::CPhysicalMemoryStack() :
  380. m_nAlignment( 16 ), m_nAdditionalFlags( 0 ), m_nUsage( 0 ), m_nPeakUsage( 0 ), m_pLastAllocedChunk( NULL ),
  381. m_nFirstAvailableChunk( 0 ), m_nChunkSizeInBytes( 0 ), m_ExtraChunks( 32, 32 ), m_nFramePeakUsage( 0 )
  382. {
  383. m_InitialChunk.m_pBase = NULL;
  384. m_InitialChunk.m_pNextAlloc = NULL;
  385. m_InitialChunk.m_pAllocLimit = NULL;
  386. }
  387. CPhysicalMemoryStack::~CPhysicalMemoryStack()
  388. {
  389. Term();
  390. }
  391. //-----------------------------------------------------------------------------
  392. // Init, shutdown
  393. //-----------------------------------------------------------------------------
  394. bool CPhysicalMemoryStack::Init( size_t nChunkSizeInBytes, size_t nAlignment, int nInitialChunkCount, uint32 nAdditionalFlags )
  395. {
  396. Assert( !m_InitialChunk.m_pBase );
  397. m_pLastAllocedChunk = NULL;
  398. m_nAdditionalFlags = nAdditionalFlags;
  399. m_nFirstAvailableChunk = 0;
  400. m_nUsage = 0;
  401. m_nFramePeakUsage = 0;
  402. m_nPeakUsage = 0;
  403. m_nAlignment = AlignValue( nAlignment, 4 );
  404. // Chunk size must be aligned to the 360 page size
  405. size_t nInitMemorySize = nChunkSizeInBytes * nInitialChunkCount;
  406. nChunkSizeInBytes = AlignValue( nChunkSizeInBytes, 64 * 1024 );
  407. m_nChunkSizeInBytes = nChunkSizeInBytes;
  408. // Fix up initial chunk count to get at least as much memory as requested
  409. // based on changes to the chunk size owing to page alignment issues
  410. nInitialChunkCount = ( nInitMemorySize + nChunkSizeInBytes - 1 ) / nChunkSizeInBytes;
  411. int nFlags = PAGE_READWRITE | nAdditionalFlags;
  412. int nAllocationSize = m_nChunkSizeInBytes * nInitialChunkCount;
  413. if ( nAllocationSize >= 16*1024*1024 )
  414. {
  415. nFlags |= MEM_16MB_PAGES;
  416. }
  417. else
  418. {
  419. nFlags |= MEM_LARGE_PAGES;
  420. }
  421. m_InitialChunk.m_pBase = (uint8*)XPhysicalAlloc( nAllocationSize, MAXULONG_PTR, 0, nFlags );
  422. if ( !m_InitialChunk.m_pBase )
  423. {
  424. m_InitialChunk.m_pNextAlloc = m_InitialChunk.m_pAllocLimit = NULL;
  425. g_pMemAlloc->OutOfMemory();
  426. return false;
  427. }
  428. m_InitialChunk.m_pNextAlloc = m_InitialChunk.m_pBase;
  429. m_InitialChunk.m_pAllocLimit = m_InitialChunk.m_pBase + nAllocationSize;
  430. MemAlloc_RegisterExternalAllocation( CPhysicalMemoryStack, m_InitialChunk.m_pBase, XPhysicalSize( m_InitialChunk.m_pBase ) );
  431. return true;
  432. }
  433. void CPhysicalMemoryStack::Term()
  434. {
  435. FreeAll();
  436. if ( m_InitialChunk.m_pBase )
  437. {
  438. MemAlloc_RegisterExternalDeallocation( CPhysicalMemoryStack, m_InitialChunk.m_pBase, XPhysicalSize( m_InitialChunk.m_pBase ) );
  439. XPhysicalFree( m_InitialChunk.m_pBase );
  440. m_InitialChunk.m_pBase = m_InitialChunk.m_pNextAlloc = m_InitialChunk.m_pAllocLimit = NULL;
  441. }
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Returns the total allocation size
  445. //-----------------------------------------------------------------------------
  446. size_t CPhysicalMemoryStack::GetSize() const
  447. {
  448. size_t nBaseSize = (intp)m_InitialChunk.m_pAllocLimit - (intp)m_InitialChunk.m_pBase;
  449. return nBaseSize + m_nChunkSizeInBytes * m_ExtraChunks.Count();
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Allocate from the 'overflow' buffers, only happens if the initial allocation
  453. // isn't good enough
  454. //-----------------------------------------------------------------------------
  455. void *CPhysicalMemoryStack::AllocFromOverflow( size_t nSizeInBytes )
  456. {
  457. // Completely full chunks are moved to the front and skipped
  458. int nCount = m_ExtraChunks.Count();
  459. for ( int i = m_nFirstAvailableChunk; i < nCount; ++i )
  460. {
  461. PhysicalChunk_t &chunk = m_ExtraChunks[i];
  462. // Here we can check if a chunk is full and move it to the head
  463. // of the list. We can't do it immediately *after* allocation
  464. // because something may later free up some of the memory
  465. if ( chunk.m_pNextAlloc == chunk.m_pAllocLimit )
  466. {
  467. if ( i > 0 )
  468. {
  469. m_ExtraChunks.FastRemove( i );
  470. m_ExtraChunks.InsertBefore( 0 );
  471. }
  472. ++m_nFirstAvailableChunk;
  473. continue;
  474. }
  475. void *pResult = chunk.m_pNextAlloc;
  476. uint8 *pNextAlloc = chunk.m_pNextAlloc + nSizeInBytes;
  477. if ( pNextAlloc > chunk.m_pAllocLimit )
  478. continue;
  479. chunk.m_pNextAlloc = pNextAlloc;
  480. m_pLastAllocedChunk = &chunk;
  481. return pResult;
  482. }
  483. // No extra chunks to use; add a new one
  484. int i = m_ExtraChunks.AddToTail();
  485. PhysicalChunk_t &chunk = m_ExtraChunks[i];
  486. int nFlags = PAGE_READWRITE | MEM_LARGE_PAGES | m_nAdditionalFlags;
  487. chunk.m_pBase = (uint8*)XPhysicalAlloc( m_nChunkSizeInBytes, MAXULONG_PTR, 0, nFlags );
  488. if ( !chunk.m_pBase )
  489. {
  490. chunk.m_pNextAlloc = chunk.m_pAllocLimit = NULL;
  491. m_pLastAllocedChunk = NULL;
  492. g_pMemAlloc->OutOfMemory();
  493. return NULL;
  494. }
  495. MemAlloc_RegisterExternalAllocation( CPhysicalMemoryStack, chunk.m_pBase, XPhysicalSize( chunk.m_pBase ) );
  496. m_pLastAllocedChunk = &chunk;
  497. chunk.m_pNextAlloc = chunk.m_pBase + nSizeInBytes;
  498. chunk.m_pAllocLimit = chunk.m_pBase + m_nChunkSizeInBytes;
  499. return chunk.m_pBase;
  500. }
  501. //-----------------------------------------------------------------------------
  502. // Allows us to free a portion of the previous allocation
  503. //-----------------------------------------------------------------------------
  504. void CPhysicalMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bUnused )
  505. {
  506. mark = AlignValue( mark, m_nAlignment );
  507. uint8 *pAllocPoint = m_pLastAllocedChunk->m_pBase + mark;
  508. Assert( pAllocPoint >= m_pLastAllocedChunk->m_pBase && pAllocPoint <= m_pLastAllocedChunk->m_pNextAlloc );
  509. if ( pAllocPoint >= m_pLastAllocedChunk->m_pBase && pAllocPoint <= m_pLastAllocedChunk->m_pNextAlloc )
  510. {
  511. m_nUsage -= (intp)m_pLastAllocedChunk->m_pNextAlloc - (intp)pAllocPoint;
  512. m_pLastAllocedChunk->m_pNextAlloc = pAllocPoint;
  513. }
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Free overflow buffers, mark initial buffer as empty
  517. //-----------------------------------------------------------------------------
  518. void CPhysicalMemoryStack::FreeAll( bool bUnused )
  519. {
  520. m_nUsage = 0;
  521. m_nFramePeakUsage = 0;
  522. m_InitialChunk.m_pNextAlloc = m_InitialChunk.m_pBase;
  523. m_pLastAllocedChunk = NULL;
  524. m_nFirstAvailableChunk = 0;
  525. int nCount = m_ExtraChunks.Count();
  526. for ( int i = 0; i < nCount; ++i )
  527. {
  528. PhysicalChunk_t &chunk = m_ExtraChunks[i];
  529. MemAlloc_RegisterExternalDeallocation( CPhysicalMemoryStack, chunk.m_pBase, XPhysicalSize( chunk.m_pBase ) );
  530. XPhysicalFree( chunk.m_pBase );
  531. }
  532. m_ExtraChunks.RemoveAll();
  533. }
  534. //-------------------------------------
  535. void CPhysicalMemoryStack::PrintContents()
  536. {
  537. Msg( "Total used memory: %8d\n", GetUsed() );
  538. Msg( "Peak used memory: %8d\n", GetPeakUsed() );
  539. Msg( "Total allocated memory: %8d\n", GetSize() );
  540. }
  541. #endif // _X360