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.

297 lines
6.4 KiB

  1. //========= Copyright 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. #endif
  15. #include "tier0/dbg.h"
  16. #include "memstack.h"
  17. #include "utlmap.h"
  18. #include "tier0/memdbgon.h"
  19. #ifdef _WIN32
  20. #pragma warning(disable:4073)
  21. #pragma init_seg(lib)
  22. #endif
  23. //-----------------------------------------------------------------------------
  24. MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
  25. //-----------------------------------------------------------------------------
  26. CMemoryStack::CMemoryStack()
  27. : m_pBase( NULL ),
  28. m_pNextAlloc( NULL ),
  29. m_pAllocLimit( NULL ),
  30. m_pCommitLimit( NULL ),
  31. m_alignment( 16 ),
  32. #if defined(_WIN32)
  33. m_commitSize( 0 ),
  34. m_minCommit( 0 ),
  35. #endif
  36. m_maxSize( 0 )
  37. {
  38. }
  39. //-------------------------------------
  40. CMemoryStack::~CMemoryStack()
  41. {
  42. if ( m_pBase )
  43. Term();
  44. }
  45. //-------------------------------------
  46. bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment )
  47. {
  48. Assert( !m_pBase );
  49. #ifdef _X360
  50. m_bPhysical = false;
  51. #endif
  52. m_maxSize = maxSize;
  53. m_alignment = AlignValue( alignment, 4 );
  54. Assert( m_alignment == alignment );
  55. Assert( m_maxSize > 0 );
  56. #if defined(_WIN32)
  57. if ( commitSize != 0 )
  58. {
  59. m_commitSize = commitSize;
  60. }
  61. unsigned pageSize;
  62. #ifndef _X360
  63. SYSTEM_INFO sysInfo;
  64. GetSystemInfo( &sysInfo );
  65. Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
  66. pageSize = sysInfo.dwPageSize;
  67. #else
  68. pageSize = 64*1024;
  69. #endif
  70. if ( m_commitSize == 0 )
  71. {
  72. m_commitSize = pageSize;
  73. }
  74. else
  75. {
  76. m_commitSize = AlignValue( m_commitSize, pageSize );
  77. }
  78. m_maxSize = AlignValue( m_maxSize, m_commitSize );
  79. Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize );
  80. m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
  81. Assert( m_pBase );
  82. m_pCommitLimit = m_pNextAlloc = m_pBase;
  83. if ( initialCommit )
  84. {
  85. initialCommit = AlignValue( initialCommit, m_commitSize );
  86. Assert( initialCommit < m_maxSize );
  87. if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
  88. return false;
  89. m_minCommit = initialCommit;
  90. m_pCommitLimit += initialCommit;
  91. MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
  92. }
  93. #else
  94. m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
  95. m_pNextAlloc = m_pBase;
  96. m_pCommitLimit = m_pBase + m_maxSize;
  97. #endif
  98. m_pAllocLimit = m_pBase + m_maxSize;
  99. return ( m_pBase != NULL );
  100. }
  101. //-------------------------------------
  102. #ifdef _X360
  103. bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment )
  104. {
  105. m_bPhysical = true;
  106. m_maxSize = m_commitSize = size;
  107. m_alignment = AlignValue( alignment, 4 );
  108. int flags = PAGE_READWRITE;
  109. if ( size >= 16*1024*1024 )
  110. {
  111. flags |= MEM_16MB_PAGES;
  112. }
  113. else
  114. {
  115. flags |= MEM_LARGE_PAGES;
  116. }
  117. m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags );
  118. Assert( m_pBase );
  119. m_pNextAlloc = m_pBase;
  120. m_pCommitLimit = m_pBase + m_maxSize;
  121. m_pAllocLimit = m_pBase + m_maxSize;
  122. MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
  123. return ( m_pBase != NULL );
  124. }
  125. #endif
  126. //-------------------------------------
  127. void CMemoryStack::Term()
  128. {
  129. FreeAll();
  130. if ( m_pBase )
  131. {
  132. #if defined(_WIN32)
  133. VirtualFree( m_pBase, 0, MEM_RELEASE );
  134. #else
  135. MemAlloc_FreeAligned( m_pBase );
  136. #endif
  137. m_pBase = NULL;
  138. }
  139. }
  140. //-------------------------------------
  141. int CMemoryStack::GetSize()
  142. {
  143. #ifdef _WIN32
  144. return m_pCommitLimit - m_pBase;
  145. #else
  146. return m_maxSize;
  147. #endif
  148. }
  149. //-------------------------------------
  150. bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
  151. {
  152. #ifdef _X360
  153. if ( m_bPhysical )
  154. {
  155. return NULL;
  156. }
  157. #endif
  158. #if defined(_WIN32)
  159. unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize );
  160. unsigned commitSize = pNewCommitLimit - m_pCommitLimit;
  161. if ( GetSize() )
  162. MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
  163. if( m_pCommitLimit + commitSize > m_pAllocLimit )
  164. {
  165. return false;
  166. }
  167. if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
  168. {
  169. Assert( 0 );
  170. return false;
  171. }
  172. m_pCommitLimit = pNewCommitLimit;
  173. if ( GetSize() )
  174. MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
  175. return true;
  176. #else
  177. Assert( 0 );
  178. return false;
  179. #endif
  180. }
  181. //-------------------------------------
  182. void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
  183. {
  184. void *pAllocPoint = m_pBase + mark;
  185. Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
  186. if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc )
  187. {
  188. if ( bDecommit )
  189. {
  190. #if defined(_WIN32)
  191. unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize );
  192. if ( pDecommitPoint < m_pBase + m_minCommit )
  193. {
  194. pDecommitPoint = m_pBase + m_minCommit;
  195. }
  196. unsigned decommitSize = m_pCommitLimit - pDecommitPoint;
  197. if ( decommitSize > 0 )
  198. {
  199. MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
  200. VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT );
  201. m_pCommitLimit = pDecommitPoint;
  202. if ( mark > 0 )
  203. {
  204. MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
  205. }
  206. }
  207. #endif
  208. }
  209. m_pNextAlloc = (unsigned char *)pAllocPoint;
  210. }
  211. }
  212. //-------------------------------------
  213. void CMemoryStack::FreeAll( bool bDecommit )
  214. {
  215. if ( m_pBase && m_pCommitLimit - m_pBase > 0 )
  216. {
  217. if ( bDecommit )
  218. {
  219. #if defined(_WIN32)
  220. MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
  221. VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT );
  222. m_pCommitLimit = m_pBase;
  223. #endif
  224. }
  225. m_pNextAlloc = m_pBase;
  226. }
  227. }
  228. //-------------------------------------
  229. void CMemoryStack::Access( void **ppRegion, unsigned *pBytes )
  230. {
  231. *ppRegion = m_pBase;
  232. *pBytes = ( m_pNextAlloc - m_pBase);
  233. }
  234. //-------------------------------------
  235. void CMemoryStack::PrintContents()
  236. {
  237. Msg( "Total used memory: %d\n", GetUsed() );
  238. Msg( "Total committed memory: %d\n", GetSize() );
  239. }
  240. //-----------------------------------------------------------------------------