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.

701 lines
21 KiB

  1. //========= Copyright � 1996-2005, 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 LINUX
  17. // Define this in release to get memory tracking even in release builds
  18. //#define USE_MEM_DEBUG 1
  19. // Define this in release to get light memory debugging
  20. //#define USE_LIGHT_MEM_DEBUG
  21. // Define this to require -uselmd to turn light memory debugging on
  22. //#define LIGHT_MEM_DEBUG_REQUIRES_CMD_LINE_SWITCH
  23. #endif
  24. #if defined( _MEMTEST )
  25. #if defined( _WIN32 ) || defined( _PS3 )
  26. #define USE_MEM_DEBUG 1
  27. #endif
  28. #endif
  29. #if defined( _PS3 )
  30. // Define STEAM_SHARES_GAME_ALLOCATOR to make Steam use the game's tier0 memory allocator.
  31. // This adds some memory to the game's Small Block Heap and Medium Block Heap, to compensate.
  32. // This configuration was disabled for Portal 2, as we could not sufficiently test it before ship.
  33. //#define STEAM_SHARES_GAME_ALLOCATOR
  34. #endif
  35. #if defined( STEAM_SHARES_GAME_ALLOCATOR )
  36. #define MBYTES_STEAM_SBH_USAGE 2
  37. #define MBYTES_STEAM_MBH_USAGE 4
  38. #else // STEAM_SHARES_GAME_ALLOCATOR
  39. #define MBYTES_STEAM_SBH_USAGE 0
  40. #define MBYTES_STEAM_MBH_USAGE 0
  41. #endif // STEAM_SHARES_GAME_ALLOCATOR
  42. // Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
  43. #define MEM_DEBUG_CLASSNAME 1
  44. #if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
  45. #include <stddef.h>
  46. #ifdef LINUX
  47. #undef offsetof
  48. #define offsetof(s,m) (size_t)&(((s *)0)->m)
  49. #endif
  50. #ifdef _PS3
  51. #define MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS 1
  52. #endif
  53. #include "tier0/mem.h"
  54. struct _CrtMemState;
  55. #define MEMALLOC_VERSION 1
  56. typedef size_t (*MemAllocFailHandler_t)( size_t );
  57. struct GenericMemoryStat_t
  58. {
  59. const char *name;
  60. int value;
  61. };
  62. // Virtual memory interface
  63. #include "tier0/memvirt.h"
  64. //-----------------------------------------------------------------------------
  65. // NOTE! This should never be called directly from leaf code
  66. // Just use new,delete,malloc,free etc. They will call into this eventually
  67. //-----------------------------------------------------------------------------
  68. abstract_class IMemAlloc
  69. {
  70. public:
  71. // Release versions
  72. virtual void *Alloc( size_t nSize ) = 0;
  73. public:
  74. virtual void *Realloc( void *pMem, size_t nSize ) = 0;
  75. virtual void Free( void *pMem ) = 0;
  76. virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize ) = 0;
  77. // Debug versions
  78. virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0;
  79. public:
  80. virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
  81. virtual void Free( void *pMem, const char *pFileName, int nLine ) = 0;
  82. virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
  83. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  84. virtual void *AllocAlign( size_t nSize, size_t align ) = 0;
  85. virtual void *AllocAlign( size_t nSize, size_t align, const char *pFileName, int nLine ) = 0;
  86. virtual void *ReallocAlign( void *pMem, size_t nSize, size_t align ) = 0;
  87. #endif
  88. inline void *IndirectAlloc( size_t nSize ) { return Alloc( nSize ); }
  89. inline void *IndirectAlloc( size_t nSize, const char *pFileName, int nLine ) { return Alloc( nSize, pFileName, nLine ); }
  90. // Returns the size of a particular allocation (NOTE: may be larger than the size requested!)
  91. virtual size_t GetSize( void *pMem ) = 0;
  92. // Force file + line information for an allocation
  93. virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0;
  94. virtual void PopAllocDbgInfo() = 0;
  95. // FIXME: Remove when we have our own allocator
  96. // these methods of the Crt debug code is used in our codebase currently
  97. virtual int32 CrtSetBreakAlloc( int32 lNewBreakAlloc ) = 0;
  98. virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0;
  99. virtual int CrtIsValidHeapPointer( const void *pMem ) = 0;
  100. virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0;
  101. virtual int CrtCheckMemory( void ) = 0;
  102. virtual int CrtSetDbgFlag( int nNewFlag ) = 0;
  103. virtual void CrtMemCheckpoint( _CrtMemState *pState ) = 0;
  104. // FIXME: Make a better stats interface
  105. virtual void DumpStats() = 0;
  106. virtual void DumpStatsFileBase( char const *pchFileBase ) = 0;
  107. virtual size_t ComputeMemoryUsedBy( char const *pchSubStr ) = 0;
  108. // FIXME: Remove when we have our own allocator
  109. virtual void* CrtSetReportFile( int nRptType, void* hFile ) = 0;
  110. virtual void* CrtSetReportHook( void* pfnNewHook ) = 0;
  111. virtual int CrtDbgReport( int nRptType, const char * szFile,
  112. int nLine, const char * szModule, const char * pMsg ) = 0;
  113. virtual int heapchk() = 0;
  114. virtual bool IsDebugHeap() = 0;
  115. virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0;
  116. virtual void RegisterAllocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
  117. virtual void RegisterDeallocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
  118. virtual int GetVersion() = 0;
  119. virtual void CompactHeap() = 0;
  120. // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
  121. virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0;
  122. virtual void DumpBlockStats( void * ) = 0;
  123. virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;
  124. // Returns 0 if no failure, otherwise the size_t of the last requested chunk
  125. virtual size_t MemoryAllocFailed() = 0;
  126. virtual void CompactIncremental() = 0;
  127. virtual void OutOfMemory( size_t nBytesAttempted = 0 ) = 0;
  128. // Region-based allocations
  129. virtual void *RegionAlloc( int region, size_t nSize ) = 0;
  130. virtual void *RegionAlloc( int region, size_t nSize, const char *pFileName, int nLine ) = 0;
  131. // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
  132. virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
  133. // Obtain virtual memory manager interface
  134. virtual IVirtualMemorySection * AllocateVirtualMemorySection( size_t numMaxBytes ) = 0;
  135. // Request 'generic' memory stats (returns a list of N named values; caller should assume this list will change over time)
  136. virtual int GetGenericMemoryStats( GenericMemoryStat_t **ppMemoryStats ) = 0;
  137. virtual ~IMemAlloc() { };
  138. // handles storing allocation info for coroutines
  139. virtual uint32 GetDebugInfoSize() = 0;
  140. virtual void SaveDebugInfo( void *pvDebugInfo ) = 0;
  141. virtual void RestoreDebugInfo( const void *pvDebugInfo ) = 0;
  142. virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) = 0;
  143. };
  144. //-----------------------------------------------------------------------------
  145. // Singleton interface
  146. //-----------------------------------------------------------------------------
  147. #ifdef _PS3
  148. PLATFORM_INTERFACE IMemAlloc * g_pMemAllocInternalPS3;
  149. #ifndef PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
  150. #define g_pMemAlloc g_pMemAllocInternalPS3
  151. #else
  152. #define g_pMemAlloc PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
  153. #endif
  154. #else // !_PS3
  155. MEM_INTERFACE IMemAlloc *g_pMemAlloc;
  156. #endif
  157. //-----------------------------------------------------------------------------
  158. #ifdef MEMALLOC_REGIONS
  159. #ifndef MEMALLOC_REGION
  160. #define MEMALLOC_REGION 0
  161. #endif
  162. inline void *MemAlloc_Alloc( size_t nSize )
  163. {
  164. return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
  165. }
  166. inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
  167. {
  168. return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
  169. }
  170. #else
  171. #undef MEMALLOC_REGION
  172. inline void *MemAlloc_Alloc( size_t nSize )
  173. {
  174. return g_pMemAlloc->IndirectAlloc( nSize );
  175. }
  176. inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
  177. {
  178. return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine );
  179. }
  180. #endif
  181. //-----------------------------------------------------------------------------
  182. #ifdef MEMALLOC_REGIONS
  183. #else
  184. #endif
  185. inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
  186. {
  187. return (value & ( value - 1 )) == 0;
  188. }
  189. inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
  190. {
  191. #ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  192. unsigned char *pAlloc, *pResult;
  193. #endif
  194. if (!ValueIsPowerOfTwo(align))
  195. return NULL;
  196. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  197. return g_pMemAlloc->AllocAlign( size, align );
  198. #else
  199. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  200. if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
  201. return NULL;
  202. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  203. ((unsigned char**)(pResult))[-1] = pAlloc;
  204. return (void *)pResult;
  205. #endif
  206. }
  207. inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
  208. {
  209. #ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  210. unsigned char *pAlloc, *pResult;
  211. #endif
  212. if (!ValueIsPowerOfTwo(align))
  213. return NULL;
  214. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  215. return g_pMemAlloc->AllocAlign( size, align, pszFile, nLine );
  216. #else
  217. align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  218. if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
  219. return NULL;
  220. pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
  221. ((unsigned char**)(pResult))[-1] = pAlloc;
  222. return (void *)pResult;
  223. #endif
  224. }
  225. #ifdef USE_MEM_DEBUG
  226. #define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
  227. #elif defined(USE_LIGHT_MEM_DEBUG)
  228. extern const char *g_pszModule;
  229. #define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
  230. #else
  231. #define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedUnattributed( s, a )
  232. #endif
  233. inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
  234. {
  235. if ( !ValueIsPowerOfTwo( align ) )
  236. return NULL;
  237. // Don't change alignment between allocation + reallocation.
  238. if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
  239. return NULL;
  240. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  241. return g_pMemAlloc->ReallocAlign( ptr, size, align );
  242. #else
  243. if ( !ptr )
  244. return MemAlloc_AllocAligned( size, align );
  245. void *pAlloc, *pResult;
  246. // Figure out the actual allocation point
  247. pAlloc = ptr;
  248. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  249. pAlloc = *( (void **)pAlloc );
  250. // See if we have enough space
  251. size_t nOffset = (size_t)ptr - (size_t)pAlloc;
  252. size_t nOldSize = g_pMemAlloc->GetSize( pAlloc );
  253. if ( nOldSize >= size + nOffset )
  254. return ptr;
  255. pResult = MemAlloc_AllocAligned( size, align );
  256. memcpy( pResult, ptr, nOldSize - nOffset );
  257. g_pMemAlloc->Free( pAlloc );
  258. return pResult;
  259. #endif
  260. }
  261. inline void MemAlloc_FreeAligned( void *pMemBlock )
  262. {
  263. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  264. g_pMemAlloc->Free( pMemBlock );
  265. #else
  266. void *pAlloc;
  267. if ( pMemBlock == NULL )
  268. return;
  269. pAlloc = pMemBlock;
  270. // pAlloc points to the pointer to starting of the memory block
  271. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  272. // pAlloc is the pointer to the start of memory block
  273. pAlloc = *( (void **)pAlloc );
  274. g_pMemAlloc->Free( pAlloc );
  275. #endif
  276. }
  277. inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
  278. {
  279. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  280. g_pMemAlloc->Free( pMemBlock, pszFile, nLine );
  281. #else
  282. void *pAlloc;
  283. if ( pMemBlock == NULL )
  284. return;
  285. pAlloc = pMemBlock;
  286. // pAlloc points to the pointer to starting of the memory block
  287. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  288. // pAlloc is the pointer to the start of memory block
  289. pAlloc = *( (void **)pAlloc );
  290. g_pMemAlloc->Free( pAlloc, pszFile, nLine );
  291. #endif
  292. }
  293. inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
  294. {
  295. #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  296. return g_pMemAlloc->GetSize( pMemBlock );
  297. #else
  298. void *pAlloc;
  299. if ( pMemBlock == NULL )
  300. return 0;
  301. pAlloc = pMemBlock;
  302. // pAlloc points to the pointer to starting of the memory block
  303. pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
  304. // pAlloc is the pointer to the start of memory block
  305. pAlloc = *((void **)pAlloc );
  306. return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc );
  307. #endif
  308. }
  309. struct aligned_tmp_t
  310. {
  311. // empty base class
  312. };
  313. // template here to allow adding alignment at levels of hierarchy that aren't the base
  314. template< int bytesAlignment = 16, class T = aligned_tmp_t >
  315. class CAlignedNewDelete : public T
  316. {
  317. public:
  318. void *operator new( size_t nSize )
  319. {
  320. return MemAlloc_AllocAligned( nSize, bytesAlignment );
  321. }
  322. void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
  323. {
  324. return MemAlloc_AllocAlignedFileLine( nSize, bytesAlignment, pFileName, nLine );
  325. }
  326. void operator delete(void *pData)
  327. {
  328. if ( pData )
  329. {
  330. MemAlloc_FreeAligned( pData );
  331. }
  332. }
  333. void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
  334. {
  335. if ( pData )
  336. {
  337. MemAlloc_FreeAligned( pData, pFileName, nLine );
  338. }
  339. }
  340. };
  341. //-----------------------------------------------------------------------------
  342. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  343. #define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ )
  344. #define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
  345. #define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
  346. #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  347. #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  348. #else
  349. #define MEM_ALLOC_CREDIT_(tag) ((void)0)
  350. #define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0)
  351. #define MemAlloc_PopAllocDbgInfo() ((void)0)
  352. #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  353. #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
  354. #endif
  355. //-----------------------------------------------------------------------------
  356. class CMemAllocAttributeAlloction
  357. {
  358. public:
  359. CMemAllocAttributeAlloction( const char *pszFile, int line )
  360. {
  361. MemAlloc_PushAllocDbgInfo( pszFile, line );
  362. }
  363. ~CMemAllocAttributeAlloction()
  364. {
  365. MemAlloc_PopAllocDbgInfo();
  366. }
  367. };
  368. #define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
  369. //-----------------------------------------------------------------------------
  370. #if defined(MSVC) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )
  371. #pragma warning(disable:4290)
  372. #pragma warning(push)
  373. #include <typeinfo.h>
  374. // MEM_DEBUG_CLASSNAME is opt-in.
  375. // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
  376. // simultaneously, it'll need a mutex.
  377. #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
  378. template <typename T> const char *MemAllocClassName( T *p )
  379. {
  380. static const char *pszName = typeid(*p).name(); // @TODO: support having debug heap ignore certain allocations, and ignore memory allocated here [5/7/2009 tom]
  381. return pszName;
  382. }
  383. #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( MemAllocClassName( this ) )
  384. #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
  385. #else
  386. #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ )
  387. #define MEM_ALLOC_CLASSNAME(type) (__FILE__)
  388. #endif
  389. // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
  390. #ifdef _MSC_VER
  391. #define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ )
  392. #else
  393. #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
  394. #endif
  395. #pragma warning(pop)
  396. #else
  397. #define MEM_ALLOC_CREDIT_CLASS()
  398. #define MEM_ALLOC_CLASSNAME(type) NULL
  399. #define MEM_ALLOC_CREDIT_FUNCTION()
  400. #endif
  401. //-----------------------------------------------------------------------------
  402. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  403. struct MemAllocFileLine_t
  404. {
  405. const char *pszFile;
  406. int line;
  407. };
  408. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
  409. static CUtlMap<void *, MemAllocFileLine_t, int> s_##tag##Allocs( DefLessFunc( void *) ); \
  410. CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs = &s_##tag##Allocs; \
  411. static CThreadFastMutex s_##tag##AllocsMutex; \
  412. CThreadFastMutex * g_p##tag##AllocsMutex = &s_##tag##AllocsMutex; \
  413. const char * g_psz##tag##Alloc = strcpy( (char *)MemAlloc_Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
  414. #define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag ) \
  415. extern CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs; \
  416. extern CThreadFastMutex *g_p##tag##AllocsMutex; \
  417. extern const char * g_psz##tag##Alloc;
  418. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
  419. if ( !p ) \
  420. ; \
  421. else \
  422. { \
  423. AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
  424. MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
  425. g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
  426. if ( fileLine.pszFile != g_psz##tag##Alloc ) \
  427. { \
  428. g_p##tag##Allocs->Insert( p, fileLine ); \
  429. } \
  430. \
  431. MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
  432. }
  433. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
  434. if ( !p ) \
  435. ; \
  436. else \
  437. { \
  438. AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
  439. MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
  440. CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_p##tag##Allocs->Find( p ); \
  441. if ( iRecordedFileLine != g_p##tag##Allocs->InvalidIndex() ) \
  442. { \
  443. fileLine = (*g_p##tag##Allocs)[iRecordedFileLine]; \
  444. g_p##tag##Allocs->RemoveAt( iRecordedFileLine ); \
  445. } \
  446. \
  447. MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
  448. }
  449. #else
  450. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
  451. #define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag )
  452. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
  453. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
  454. #endif
  455. //-----------------------------------------------------------------------------
  456. #endif // !STEAM && !NO_MALLOC_OVERRIDE
  457. //-----------------------------------------------------------------------------
  458. #if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
  459. #include <malloc.h>
  460. #define MEM_ALLOC_CREDIT_(tag) ((void)0)
  461. #define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
  462. #define MEM_ALLOC_CREDIT_CLASS()
  463. #define MEM_ALLOC_CLASSNAME(type) NULL
  464. #define MemAlloc_PushAllocDbgInfo( pszFile, line )
  465. #define MemAlloc_PopAllocDbgInfo()
  466. #define MemAlloc_RegisterAllocation( a,b,c,d,e ) ((void)0)
  467. #define MemAlloc_RegisterDeallocation( a,b,c,d,e ) ((void)0)
  468. #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
  469. #define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
  470. #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
  471. inline void *MemAlloc_AllocAligned( size_t size, size_t align )
  472. {
  473. return (void *)_aligned_malloc( size, align );
  474. }
  475. inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
  476. {
  477. pszFile = pszFile;
  478. nLine = nLine;
  479. return (void *)_aligned_malloc( size, align );
  480. }
  481. inline void MemAlloc_FreeAligned( void *pMemBlock )
  482. {
  483. _aligned_free( pMemBlock );
  484. }
  485. inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
  486. {
  487. pszFile = pszFile;
  488. nLine = nLine;
  489. _aligned_free( pMemBlock );
  490. }
  491. #endif // !STEAM && NO_MALLOC_OVERRIDE
  492. //-----------------------------------------------------------------------------
  493. // linux memory tracking via hooks.
  494. #if defined( POSIX ) && !defined( _PS3 )
  495. PLATFORM_INTERFACE void MemoryLogMessage( char const *s ); // throw a message into the memory log
  496. PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
  497. PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
  498. PLATFORM_INTERFACE void DumpMemorySummary( void );
  499. PLATFORM_INTERFACE void SetMemoryMark( void );
  500. PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
  501. // ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
  502. PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
  503. #else
  504. inline void MemoryLogMessage( char const * )
  505. {
  506. }
  507. inline void EnableMemoryLogging( bool )
  508. {
  509. }
  510. inline void DumpMemoryLog( int )
  511. {
  512. }
  513. inline void DumpMemorySummary( void )
  514. {
  515. }
  516. inline void SetMemoryMark( void )
  517. {
  518. }
  519. inline void DumpChangedMemory( int )
  520. {
  521. }
  522. inline size_t ApproximateProcessMemoryUsage( void )
  523. {
  524. return 0;
  525. }
  526. #endif
  527. #endif /* TIER0_MEMALLOC_H */