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.

169 lines
4.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // ZONE MEMORY ALLOCATION
  6. //
  7. // There is never any space between memblocks, and there will never be two
  8. // contiguous free memblocks.
  9. //
  10. // The rover can be left pointing at a non-empty block
  11. //
  12. // The zone calls are pretty much only used for small strings and structures,
  13. // all big things are allocated on the hunk.
  14. //=============================================================================//
  15. #include "basetypes.h"
  16. #include "zone.h"
  17. #include "host.h"
  18. #include "tier1/strtools.h"
  19. #include "tier0/icommandline.h"
  20. #include "memstack.h"
  21. #include "datacache/idatacache.h"
  22. #include "sys_dll.h"
  23. #include "tier0/memalloc.h"
  24. #define MINIMUM_WIN_MEMORY 0x03000000 // FIXME: copy from sys_dll.cpp, find a common header at some point
  25. #ifdef _X360
  26. #define HUNK_USE_16MB_PAGE
  27. #endif
  28. CMemoryStack g_HunkMemoryStack;
  29. #ifdef HUNK_USE_16MB_PAGE
  30. CMemoryStack g_HunkOverflow;
  31. static bool g_bWarnedOverflow;
  32. #endif
  33. static int GetTargetCacheSize()
  34. {
  35. int nMemLimit = host_parms.memsize - Hunk_Size();
  36. if ( nMemLimit < 0x100000 )
  37. {
  38. nMemLimit = 0x100000;
  39. }
  40. return nMemLimit;
  41. }
  42. /*
  43. ===================
  44. Hunk_AllocName
  45. ===================
  46. */
  47. void *Hunk_AllocName (int size, const char *name, bool bClear)
  48. {
  49. MEM_ALLOC_CREDIT();
  50. void * p = g_HunkMemoryStack.Alloc( size, bClear );
  51. if ( p )
  52. return p;
  53. #ifdef HUNK_USE_16MB_PAGE
  54. if ( !g_bWarnedOverflow )
  55. {
  56. g_bWarnedOverflow = true;
  57. DevMsg( "Note: Hunk base page exhausted\n" );
  58. }
  59. p = g_HunkOverflow.Alloc( size, bClear );
  60. if ( p )
  61. return p;
  62. #endif
  63. Error( "Engine hunk overflow!\n" );
  64. return NULL;
  65. }
  66. /*
  67. ===================
  68. Hunk_Alloc
  69. ===================
  70. */
  71. void *Hunk_Alloc(int size, bool bClear )
  72. {
  73. MEM_ALLOC_CREDIT();
  74. return Hunk_AllocName( size, NULL, bClear );
  75. }
  76. int Hunk_LowMark(void)
  77. {
  78. return (int)( g_HunkMemoryStack.GetCurrentAllocPoint() );
  79. }
  80. void Hunk_FreeToLowMark(int mark)
  81. {
  82. Assert( mark < g_HunkMemoryStack.GetSize() );
  83. #ifdef HUNK_USE_16MB_PAGE
  84. g_HunkOverflow.FreeAll();
  85. g_bWarnedOverflow = false;
  86. #endif
  87. g_HunkMemoryStack.FreeToAllocPoint( mark );
  88. }
  89. int Hunk_MallocSize()
  90. {
  91. #ifdef HUNK_USE_16MB_PAGE
  92. return g_HunkMemoryStack.GetSize() + g_HunkOverflow.GetSize();
  93. #else
  94. return g_HunkMemoryStack.GetSize();
  95. #endif
  96. }
  97. int Hunk_Size()
  98. {
  99. #ifdef HUNK_USE_16MB_PAGE
  100. return g_HunkMemoryStack.GetUsed() + g_HunkOverflow.GetUsed();
  101. #else
  102. return g_HunkMemoryStack.GetUsed();
  103. #endif
  104. }
  105. void Hunk_Print()
  106. {
  107. #ifdef HUNK_USE_16MB_PAGE
  108. Msg( "Total used memory: %d (%d/%d)\n", Hunk_Size(), g_HunkMemoryStack.GetUsed(), g_HunkOverflow.GetUsed() );
  109. Msg( "Total committed memory: %d (%d/%d)\n", Hunk_MallocSize(), g_HunkMemoryStack.GetSize(), g_HunkOverflow.GetSize() );
  110. #else
  111. Msg( "Total used memory: %d\n", Hunk_Size() );
  112. Msg( "Total committed memory: %d\n", Hunk_MallocSize() );
  113. #endif
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose:
  117. //-----------------------------------------------------------------------------
  118. void Memory_Init( void )
  119. {
  120. MEM_ALLOC_CREDIT();
  121. int nMaxBytes = 48*1024*1024;
  122. const int nMinCommitBytes = 0x8000;
  123. #ifndef HUNK_USE_16MB_PAGE
  124. const int nInitialCommit = 0x280000;
  125. while ( !g_HunkMemoryStack.Init( nMaxBytes, nMinCommitBytes, nInitialCommit ) )
  126. {
  127. Warning( "Unable to allocate %d MB of memory, trying %d MB instead\n", nMaxBytes, nMaxBytes/2 );
  128. nMaxBytes /= 2;
  129. if ( nMaxBytes < MINIMUM_WIN_MEMORY )
  130. {
  131. Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", MINIMUM_WIN_MEMORY/(1024*1024));
  132. }
  133. }
  134. #else
  135. if ( !g_HunkMemoryStack.InitPhysical( 16*1024*1024 ) || !g_HunkOverflow.Init( nMaxBytes - 16*1024*1024, nMinCommitBytes ) )
  136. {
  137. Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", nMaxBytes );
  138. }
  139. #endif
  140. g_pDataCache->SetSize( GetTargetCacheSize() );
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose:
  144. //-----------------------------------------------------------------------------
  145. void Memory_Shutdown( void )
  146. {
  147. g_HunkMemoryStack.FreeAll();
  148. // This disconnects the engine data cache
  149. g_pDataCache->SetSize( 0 );
  150. }