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.

661 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: This header should never be used directly from leaf code!!!
  4. // Instead, just add the file memoverride.cpp into your project and all this
  5. // will automagically be used
  6. //
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #ifndef TIER0_MEMALLOC_H
  10. #define TIER0_MEMALLOC_H
  11. #ifdef _WIN32
  12. #pragma once
  13. #endif
  14. // These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
  15. // isn't built into Linux projects
  16. #ifndef POSIX
  17. // Define this in release to get memory tracking even in release builds
  18. //#define USE_MEM_DEBUG 1
  19. #endif
  20. #if defined( _MEMTEST )
  21. #ifdef _WIN32
  22. #define USE_MEM_DEBUG 1
  23. #endif
  24. #endif
  25. // Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
  26. #define MEM_DEBUG_CLASSNAME 1
  27. #include <stddef.h>
  28. #if defined( OSX )
  29. #include <malloc/malloc.h>
  30. #endif
  31. #include "tier0/mem.h"
  32. #if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
  33. struct _CrtMemState;
  34. #define MEMALLOC_VERSION 1
  35. typedef size_t (*MemAllocFailHandler_t)( size_t );
  36. //-----------------------------------------------------------------------------
  37. // NOTE! This should never be called directly from leaf code
  38. // Just use new,delete,malloc,free etc. They will call into this eventually
  39. //-----------------------------------------------------------------------------
  40. abstract_class IMemAlloc
  41. {
  42. public:
  43. // Release versions
  44. virtual void *Alloc( size_t nSize ) = 0;
  45. virtual void *Realloc( void *pMem, size_t nSize ) = 0;
  46. virtual void Free( void *pMem ) = 0;
  47. virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize ) = 0;
  48. // Debug versions
  49. virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0;
  50. virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
  51. virtual void Free( void *pMem, const char *pFileName, int nLine ) = 0;
  52. virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
  53. // Returns size of a particular allocation
  54. virtual size_t GetSize( void *pMem ) = 0;
  55. // Force file + line information for an allocation
  56. virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0;
  57. virtual void PopAllocDbgInfo() = 0;
  58. // FIXME: Remove when we have our own allocator
  59. // these methods of the Crt debug code is used in our codebase currently
  60. virtual long CrtSetBreakAlloc( long lNewBreakAlloc ) = 0;
  61. virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0;
  62. virtual int CrtIsValidHeapPointer( const void *pMem ) = 0;
  63. virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0;
  64. virtual int CrtCheckMemory( void ) = 0;
  65. virtual int CrtSetDbgFlag( int nNewFlag ) = 0;
  66. virtual void CrtMemCheckpoint( _CrtMemState *pState ) = 0;
  67. // FIXME: Make a better stats interface
  68. virtual void DumpStats() = 0;
  69. virtual void DumpStatsFileBase( char const *pchFileBase ) = 0;
  70. // FIXME: Remove when we have our own allocator
  71. virtual void* CrtSetReportFile( int nRptType, void* hFile ) = 0;
  72. virtual void* CrtSetReportHook( void* pfnNewHook ) = 0;
  73. virtual int CrtDbgReport( int nRptType, const char * szFile,
  74. int nLine, const char * szModule, const char * pMsg ) = 0;
  75. virtual int heapchk() = 0;
  76. virtual bool IsDebugHeap() = 0;
  77. virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0;
  78. virtual void RegisterAllocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0;
  79. virtual void RegisterDeallocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0;
  80. virtual int GetVersion() = 0;
  81. virtual void CompactHeap() = 0;
  82. // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
  83. virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0;
  84. virtual void DumpBlockStats( void * ) = 0;
  85. #if defined( _MEMTEST )
  86. virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;
  87. #endif
  88. // Returns 0 if no failure, otherwise the size_t of the last requested chunk
  89. // "I'm sure this is completely thread safe!" Brian Deen 7/19/2012.
  90. virtual size_t MemoryAllocFailed() = 0;
  91. // handles storing allocation info for coroutines
  92. virtual uint32 GetDebugInfoSize() = 0;
  93. virtual void SaveDebugInfo( void *pvDebugInfo ) = 0;
  94. virtual void RestoreDebugInfo( const void *pvDebugInfo ) = 0;
  95. virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) = 0;
  96. // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
  97. virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
  98. };
  99. //-----------------------------------------------------------------------------
  100. // Singleton interface
  101. //-----------------------------------------------------------------------------
  102. MEM_INTERFACE IMemAlloc *g_pMemAlloc;
  103. //-----------------------------------------------------------------------------
  104. #ifdef MEMALLOC_REGIONS
  105. #ifndef MEMALLOC_REGION
  106. #define MEMALLOC_REGION 0
  107. #endif
  108. inline void *MemAlloc_Alloc( size_t nSize )
  109. {
  110. return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
  111. }
  112. inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
  113. {
  114. return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
  115. }
  116. #else
  117. #undef MEMALLOC_REGION
  118. inline void *MemAlloc_Alloc( size_t nSize )
  119. {
  120. return g_pMemAlloc->Alloc( nSize );
  121. }
  122. inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
  123. {
  124. return g_pMemAlloc->Alloc( nSize, pFileName, nLine );
  125. }
  126. #endif
  127. inline void MemAlloc_Free( void *ptr )
  128. {
  129. g_pMemAlloc->Free( ptr );
  130. }
  131. inline void MemAlloc_Free( void *ptr, const char *pFileName, int nLine )
  132. {
  133. g_pMemAlloc->Free( ptr, pFileName, nLine );
  134. }
  135. //-----------------------------------------------------------------------------
  136. inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
  137. {
  138. return (value & ( value - 1 )) == 0;
  139. }
  140. inline void *MemAlloc_AllocAligned( size_t size, size_t align )
  141. {
  142. unsigned char *pAlloc, *pResult;
  143. if (!IsPowerOfTwo(align))
  144. return NULL;
  145. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  146. if ( (pAlloc = (unsigned char*)g_pMemAlloc->Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
  147. return NULL;
  148. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  149. ((unsigned char**)(pResult))[-1] = pAlloc;
  150. return (void *)pResult;
  151. }
  152. inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
  153. {
  154. unsigned char *pAlloc, *pResult;
  155. if (!IsPowerOfTwo(align))
  156. return NULL;
  157. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  158. if ( (pAlloc = (unsigned char*)g_pMemAlloc->Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
  159. return NULL;
  160. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  161. ((unsigned char**)(pResult))[-1] = pAlloc;
  162. return (void *)pResult;
  163. }
  164. inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
  165. {
  166. unsigned char *pAlloc, *pResult;
  167. if (!ValueIsPowerOfTwo(align))
  168. return NULL;
  169. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  170. if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
  171. return NULL;
  172. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  173. ((unsigned char**)(pResult))[-1] = pAlloc;
  174. return (void *)pResult;
  175. }
  176. inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
  177. {
  178. unsigned char *pAlloc, *pResult;
  179. if (!ValueIsPowerOfTwo(align))
  180. return NULL;
  181. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  182. if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
  183. return NULL;
  184. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  185. ((unsigned char**)(pResult))[-1] = pAlloc;
  186. return (void *)pResult;
  187. }
  188. inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
  189. {
  190. if ( !IsPowerOfTwo( align ) )
  191. return NULL;
  192. // Don't change alignment between allocation + reallocation.
  193. if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
  194. return NULL;
  195. if ( !ptr )
  196. return MemAlloc_AllocAligned( size, align );
  197. void *pAlloc, *pResult;
  198. // Figure out the actual allocation point
  199. pAlloc = ptr;
  200. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  201. pAlloc = *( (void **)pAlloc );
  202. // See if we have enough space
  203. size_t nOffset = (size_t)ptr - (size_t)pAlloc;
  204. size_t nOldSize = g_pMemAlloc->GetSize( pAlloc );
  205. if ( nOldSize >= size + nOffset )
  206. return ptr;
  207. pResult = MemAlloc_AllocAligned( size, align );
  208. memcpy( pResult, ptr, nOldSize - nOffset );
  209. g_pMemAlloc->Free( pAlloc );
  210. return pResult;
  211. }
  212. inline void MemAlloc_FreeAligned( void *pMemBlock )
  213. {
  214. void *pAlloc;
  215. if ( pMemBlock == NULL )
  216. return;
  217. pAlloc = pMemBlock;
  218. // pAlloc points to the pointer to starting of the memory block
  219. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  220. // pAlloc is the pointer to the start of memory block
  221. pAlloc = *( (void **)pAlloc );
  222. g_pMemAlloc->Free( pAlloc );
  223. }
  224. inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pFileName, int nLine )
  225. {
  226. void *pAlloc;
  227. if ( pMemBlock == NULL )
  228. return;
  229. pAlloc = pMemBlock;
  230. // pAlloc points to the pointer to starting of the memory block
  231. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  232. // pAlloc is the pointer to the start of memory block
  233. pAlloc = *( (void **)pAlloc );
  234. g_pMemAlloc->Free( pAlloc, pFileName, nLine );
  235. }
  236. inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
  237. {
  238. void *pAlloc;
  239. if ( pMemBlock == NULL )
  240. return 0;
  241. pAlloc = pMemBlock;
  242. // pAlloc points to the pointer to starting of the memory block
  243. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  244. // pAlloc is the pointer to the start of memory block
  245. pAlloc = *((void **)pAlloc );
  246. return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc );
  247. }
  248. //-----------------------------------------------------------------------------
  249. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  250. #define MEM_ALLOC_CREDIT_JOIN_AGAIN( a, b ) a ## b
  251. #define MEM_ALLOC_CREDIT_JOIN( a, b ) MEM_ALLOC_CREDIT_JOIN_AGAIN( a, b )
  252. #define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction MEM_ALLOC_CREDIT_JOIN( memAllocAttributeAlloction, __LINE__ )( tag, __LINE__ )
  253. #define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
  254. #define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
  255. #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  256. #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  257. #else
  258. #define MEM_ALLOC_CREDIT_(tag) ((void)0)
  259. #define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0)
  260. #define MemAlloc_PopAllocDbgInfo() ((void)0)
  261. #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  262. #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  263. #endif
  264. #define MemAlloc_DumpStats() g_pMemAlloc->DumpStats()
  265. #define MemAlloc_CompactHeap() g_pMemAlloc->CompactHeap()
  266. #define MemAlloc_CompactIncremental() g_pMemAlloc->CompactIncremental()
  267. #define MemAlloc_DumpStatsFileBase( _filename ) g_pMemAlloc->DumpStatsFileBase( _filename )
  268. #define MemAlloc_CrtCheckMemory() g_pMemAlloc->CrtCheckMemory()
  269. #define MemAlloc_GlobalMemoryStatus( _usedMemory, _freeMemory ) g_pMemAlloc->GlobalMemoryStatus( _usedMemory, _freeMemory )
  270. #define MemAlloc_MemoryAllocFailed() g_pMemAlloc->MemoryAllocFailed()
  271. #define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
  272. #define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
  273. #define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
  274. #define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
  275. #define MemAlloc_GetSize( x ) g_pMemAlloc->GetSize( x );
  276. //-----------------------------------------------------------------------------
  277. class CMemAllocAttributeAlloction
  278. {
  279. public:
  280. CMemAllocAttributeAlloction( const char *pszFile, int line )
  281. {
  282. MemAlloc_PushAllocDbgInfo( pszFile, line );
  283. }
  284. ~CMemAllocAttributeAlloction()
  285. {
  286. MemAlloc_PopAllocDbgInfo();
  287. }
  288. };
  289. #define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
  290. //-----------------------------------------------------------------------------
  291. #if defined(_WIN32) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )
  292. #pragma warning(disable:4290)
  293. #pragma warning(push)
  294. #include <typeinfo.h>
  295. // MEM_DEBUG_CLASSNAME is opt-in.
  296. // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
  297. // simultaneously, it'll need a mutex.
  298. #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
  299. #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( typeid(*this).name() )
  300. #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
  301. #else
  302. #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ )
  303. #define MEM_ALLOC_CLASSNAME(type) (__FILE__)
  304. #endif
  305. // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
  306. #ifdef _MSC_VER
  307. #define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ )
  308. #else
  309. #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
  310. #endif
  311. #pragma warning(pop)
  312. #else
  313. #define MEM_ALLOC_CREDIT_CLASS()
  314. #define MEM_ALLOC_CLASSNAME(type) NULL
  315. #define MEM_ALLOC_CREDIT_FUNCTION()
  316. #endif
  317. //-----------------------------------------------------------------------------
  318. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  319. struct MemAllocFileLine_t
  320. {
  321. const char *pszFile;
  322. int line;
  323. };
  324. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
  325. static CUtlMap<void *, MemAllocFileLine_t, int> g_##tag##Allocs( DefLessFunc( void *) ); \
  326. static const char *g_psz##tag##Alloc = strcpy( (char *)g_pMemAlloc->Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
  327. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
  328. if ( !p ) \
  329. ; \
  330. else \
  331. { \
  332. MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
  333. g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
  334. if ( fileLine.pszFile != g_psz##tag##Alloc ) \
  335. { \
  336. g_##tag##Allocs.Insert( p, fileLine ); \
  337. } \
  338. \
  339. MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
  340. }
  341. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
  342. if ( !p ) \
  343. ; \
  344. else \
  345. { \
  346. MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
  347. CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_##tag##Allocs.Find( p ); \
  348. if ( iRecordedFileLine != g_##tag##Allocs.InvalidIndex() ) \
  349. { \
  350. fileLine = g_##tag##Allocs[iRecordedFileLine]; \
  351. g_##tag##Allocs.RemoveAt( iRecordedFileLine ); \
  352. } \
  353. \
  354. MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
  355. }
  356. #else
  357. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
  358. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
  359. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
  360. #endif
  361. //-----------------------------------------------------------------------------
  362. #elif defined( POSIX )
  363. inline void MemAlloc_CheckAlloc( void *ptr, size_t nSize )
  364. {
  365. if ( !ptr )
  366. MemAllocOOMError( nSize );
  367. }
  368. #if defined( OSX )
  369. // Mac always aligns allocs, don't need to call posix_memalign which doesn't exist in 10.5.8 which TF2 still needs to run on
  370. //inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; posix_memalign(&pTmp, alignment, size); return pTmp;}
  371. inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; pTmp = malloc(size); MemAlloc_CheckAlloc( pTmp, size ); return pTmp;}
  372. #endif
  373. inline void *_aligned_malloc( size_t nSize, size_t align ) { void *ptr = memalign( align, nSize ); MemAlloc_CheckAlloc( ptr, nSize ); return ptr; }
  374. inline void _aligned_free( void *ptr ) { free( ptr ); }
  375. inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName = NULL, int nLine = 0 ) { void *ptr = malloc( nSize ); MemAlloc_CheckAlloc( ptr, nSize ); return ptr; }
  376. inline void MemAlloc_Free( void *ptr, const char *pFileName = NULL, int nLine = 0 ) { free( ptr ); }
  377. inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { void *ptr = memalign( align, size ); MemAlloc_CheckAlloc( ptr, size ); return ptr; }
  378. inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { void *ptr = memalign( align, size ); MemAlloc_CheckAlloc( ptr, size ); return ptr; }
  379. inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile = NULL, int nLine = 0 ) { free( pMemBlock ); }
  380. #if defined( OSX )
  381. inline size_t _msize( void *ptr ) { return malloc_size( ptr ); }
  382. #else
  383. inline size_t _msize( void *ptr ) { return malloc_usable_size( ptr ); }
  384. #endif
  385. inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
  386. {
  387. void *ptr_new_aligned = memalign( align, size );
  388. if( ptr_new_aligned )
  389. {
  390. size_t old_size = _msize( ptr );
  391. size_t copy_size = ( size < old_size ) ? size : old_size;
  392. memcpy( ptr_new_aligned, ptr, copy_size );
  393. free( ptr );
  394. }
  395. MemAlloc_CheckAlloc( ptr_new_aligned, size );
  396. return ptr_new_aligned;
  397. }
  398. #else
  399. #define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
  400. #define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
  401. #define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
  402. #define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
  403. #endif // !STEAM && !NO_MALLOC_OVERRIDE
  404. //-----------------------------------------------------------------------------
  405. #if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
  406. #define MEM_ALLOC_CREDIT_(tag) ((void)0)
  407. #define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
  408. #define MEM_ALLOC_CREDIT_FUNCTION()
  409. #define MEM_ALLOC_CREDIT_CLASS()
  410. #define MEM_ALLOC_CLASSNAME(type) NULL
  411. #define MemAlloc_PushAllocDbgInfo( pszFile, line )
  412. #define MemAlloc_PopAllocDbgInfo()
  413. #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  414. #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  415. #define MemAlloc_DumpStats() ((void)0)
  416. #define MemAlloc_CompactHeap() ((void)0)
  417. #define MemAlloc_CompactIncremental() ((void)0)
  418. #define MemAlloc_DumpStatsFileBase( _filename ) ((void)0)
  419. inline bool MemAlloc_CrtCheckMemory() { return true; }
  420. inline void MemAlloc_GlobalMemoryStatus( size_t *pusedMemory, size_t *pfreeMemory )
  421. {
  422. *pusedMemory = 0;
  423. *pfreeMemory = 0;
  424. }
  425. #define MemAlloc_MemoryAllocFailed() 0
  426. #define MemAlloc_GetDebugInfoSize() 0
  427. #define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0)
  428. #define MemAlloc_RestoreDebugInfo( pvDebugInfo ) ((void)0)
  429. #define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) ((void)0)
  430. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
  431. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
  432. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
  433. #endif // !STEAM && NO_MALLOC_OVERRIDE
  434. //-----------------------------------------------------------------------------
  435. // linux memory tracking via hooks.
  436. #if defined( POSIX ) && !defined( NO_HOOK_MALLOC )
  437. PLATFORM_INTERFACE void MemoryLogMessage( char const *s ); // throw a message into the memory log
  438. PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
  439. PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
  440. PLATFORM_INTERFACE void DumpMemorySummary( void );
  441. PLATFORM_INTERFACE void SetMemoryMark( void );
  442. PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
  443. #else
  444. FORCEINLINE void MemoryLogMessage( char const *s )
  445. {
  446. }
  447. FORCEINLINE void EnableMemoryLogging( bool bOnOff )
  448. {
  449. }
  450. FORCEINLINE void DumpMemoryLog( int nThresh )
  451. {
  452. }
  453. FORCEINLINE void DumpMemorySummary( void )
  454. {
  455. }
  456. FORCEINLINE void SetMemoryMark( void )
  457. {
  458. }
  459. FORCEINLINE void DumpChangedMemory( int nThresh )
  460. {
  461. }
  462. #endif
  463. #ifdef POSIX
  464. // ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
  465. PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
  466. #else
  467. FORCEINLINE size_t ApproximateProcessMemoryUsage( void )
  468. {
  469. return 0;
  470. }
  471. #endif
  472. struct aligned_tmp_t
  473. {
  474. // empty base class
  475. };
  476. /*
  477. This class used to be required if you wanted an object to be allocated with a specific
  478. alignment. ALIGN16 and ALIGN16_POST are not actually sufficient for this because they
  479. guarantee that the globals, statics, locals, and function parameters are appropriately
  480. aligned they do not affect memory allocation alignment.
  481. However this class is usually not needed because as of 2012 our policy is that our
  482. allocator should take care of this automatically. Any object whose size is a multiple
  483. of 16 will be 16-byte aligned. Existing uses of this class were not changed because
  484. the cost/benefit did not justify it.
  485. */
  486. // template here to allow adding alignment at levels of hierarchy that aren't the base
  487. template< int bytesAlignment = 16, class T = aligned_tmp_t >
  488. class CAlignedNewDelete : public T
  489. {
  490. public:
  491. /*
  492. Note that this class does not overload operator new[] and delete[] which means that
  493. classes that depend on this for alignment may end up misaligned if an array is
  494. allocated. This problem is now mostly theoretical because this class is mostly
  495. obsolete.
  496. */
  497. void *operator new( size_t nSize )
  498. {
  499. return MemAlloc_AllocAligned( nSize, bytesAlignment );
  500. }
  501. void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
  502. {
  503. return MemAlloc_AllocAlignedFileLine( nSize, bytesAlignment, pFileName, nLine );
  504. }
  505. void operator delete(void *pData)
  506. {
  507. if ( pData )
  508. {
  509. MemAlloc_FreeAligned( pData );
  510. }
  511. }
  512. void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
  513. {
  514. if ( pData )
  515. {
  516. MemAlloc_FreeAligned( pData, pFileName, nLine );
  517. }
  518. }
  519. };
  520. #endif /* TIER0_MEMALLOC_H */