text: ﻿//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  //
  // Purpose: This header should never be used directly from leaf code!!!
  // Instead, just add the file memoverride.cpp into your project and all this
  // will automagically be used
  //
  // $NoKeywords: $
  //=============================================================================//
  
  #ifndef TIER0_MEMALLOC_H
  #define TIER0_MEMALLOC_H
  
  #ifdef _WIN32
  #pragma once
  #endif
  
  // These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
  // isn't built into Linux projects
  #ifndef LINUX
  // Define this in release to get memory tracking even in release builds
  //#define USE_MEM_DEBUG 1
  
  // Define this in release to get light memory debugging
  //#define USE_LIGHT_MEM_DEBUG
  
  // Define this to require -uselmd to turn light memory debugging on
  //#define LIGHT_MEM_DEBUG_REQUIRES_CMD_LINE_SWITCH
  #endif
  
  #if defined( _MEMTEST )
  #if defined( _WIN32 ) || defined( _PS3 )
  #define USE_MEM_DEBUG 1
  #endif
  #endif
  
  
  #if defined( _PS3 )
  // Define STEAM_SHARES_GAME_ALLOCATOR to make Steam use the game's tier0 memory allocator.
  // This adds some memory to the game's Small Block Heap and Medium Block Heap, to compensate.
  // This configuration was disabled for Portal 2, as we could not sufficiently test it before ship.
  //#define STEAM_SHARES_GAME_ALLOCATOR
  #endif
  
  #if defined( STEAM_SHARES_GAME_ALLOCATOR )
  #define MBYTES_STEAM_SBH_USAGE 2
  #define MBYTES_STEAM_MBH_USAGE 4
  #else // STEAM_SHARES_GAME_ALLOCATOR
  #define MBYTES_STEAM_SBH_USAGE 0
  #define MBYTES_STEAM_MBH_USAGE 0
  #endif // STEAM_SHARES_GAME_ALLOCATOR
  
  // Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
  #define MEM_DEBUG_CLASSNAME 1
  
  #if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
  
  #include <stddef.h>
  
  #ifdef LINUX
  #undef offsetof
  #define offsetof(s,m)	(size_t)&(((s *)0)->m)
  #endif
  
  #ifdef _PS3
  #define MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS 1
  #endif
  
  #include "tier0/mem.h"
  
  struct _CrtMemState;
  
  #define MEMALLOC_VERSION 1
  
  typedef size_t (*MemAllocFailHandler_t)(size_t);
  
  struct GenericMemoryStat_t {
      const char *name;
      int value;
  };
  
  
  // Virtual memory interface
  #include "tier0/memvirt.h"
  
  
  //-----------------------------------------------------------------------------
  // NOTE! This should never be called directly from leaf code
  // Just use new,delete,malloc,free etc. They will call into this eventually
  //-----------------------------------------------------------------------------
  abstract_class IMemAlloc {
  public:
      // Release versions
      virtual void *Alloc(size_t nSize) = 0;
  
  public:
      virtual void *Realloc(void *pMem, size_t nSize) = 0;
  
      virtual void Free(void *pMem) = 0;
  
      virtual void *Expand_NoLongerSupported(void *pMem, size_t nSize) = 0;
  
      // Debug versions
      virtual void *Alloc(size_t nSize, const char *pFileName, int nLine) = 0;
  
  public:
      virtual void *Realloc(void *pMem, size_t nSize, const char *pFileName, int nLine) = 0;
  
      virtual void Free(void *pMem, const char *pFileName, int nLine) = 0;
  
      virtual void *Expand_NoLongerSupported(void *pMem, size_t nSize, const char *pFileName, int nLine) = 0;
  
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
      virtual void *AllocAlign( size_t nSize, size_t align ) = 0;
      virtual void *AllocAlign( size_t nSize, size_t align, const char *pFileName, int nLine ) = 0;
      virtual void *ReallocAlign( void *pMem, size_t nSize, size_t align ) = 0;
  #endif
  
      inline void *IndirectAlloc(size_t nSize) { return Alloc(nSize); }
  
      inline void *IndirectAlloc(size_t nSize, const char *pFileName, int nLine) {
          return Alloc(nSize, pFileName, nLine);
      }
  
      // Returns the size of a particular allocation (NOTE: may be larger than the size requested!)
      virtual size_t GetSize(void *pMem) = 0;
  
      // Force file + line information for an allocation
      virtual void PushAllocDbgInfo(const char *pFileName, int nLine) = 0;
  
      virtual void PopAllocDbgInfo() = 0;
  
      // FIXME: Remove when we have our own allocator
      // these methods of the Crt debug code is used in our codebase currently
      virtual int32 CrtSetBreakAlloc(int32 lNewBreakAlloc) = 0;
  
      virtual int CrtSetReportMode(int nReportType, int nReportMode) = 0;
  
      virtual int CrtIsValidHeapPointer(const void *pMem) = 0;
  
      virtual int CrtIsValidPointer(const void *pMem, unsigned int size, int access) = 0;
  
      virtual int CrtCheckMemory(void) = 0;
  
      virtual int CrtSetDbgFlag(int nNewFlag) = 0;
  
      virtual void CrtMemCheckpoint(_CrtMemState *pState) = 0;
  
      // FIXME: Make a better stats interface
      virtual void DumpStats() = 0;
  
      virtual void DumpStatsFileBase(char const *pchFileBase) = 0;
  
      virtual size_t ComputeMemoryUsedBy(char const *pchSubStr) = 0;
  
      // FIXME: Remove when we have our own allocator
      virtual void *CrtSetReportFile(int nRptType, void *hFile) = 0;
  
      virtual void *CrtSetReportHook(void *pfnNewHook) = 0;
  
      virtual int CrtDbgReport(int nRptType, const char *szFile,
                               int nLine, const char *szModule, const char *pMsg) = 0;
  
      virtual int heapchk() = 0;
  
      virtual bool IsDebugHeap() = 0;
  
      virtual void GetActualDbgInfo(const char *&pFileName, int &nLine) = 0;
  
      virtual void
      RegisterAllocation(const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime) = 0;
  
      virtual void
      RegisterDeallocation(const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime) = 0;
  
      virtual int GetVersion() = 0;
  
      virtual void CompactHeap() = 0;
  
      // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
      virtual MemAllocFailHandler_t SetAllocFailHandler(MemAllocFailHandler_t pfnMemAllocFailHandler) = 0;
  
      virtual void DumpBlockStats(void *) = 0;
  
      virtual void SetStatsExtraInfo(const char *pMapName, const char *pComment) = 0;
  
      // Returns 0 if no failure, otherwise the size_t of the last requested chunk
      virtual size_t MemoryAllocFailed() = 0;
  
      virtual void CompactIncremental() = 0;
  
      virtual void OutOfMemory(size_t nBytesAttempted = 0) = 0;
  
      // Region-based allocations
      virtual void *RegionAlloc(int region, size_t nSize) = 0;
  
      virtual void *RegionAlloc(int region, size_t nSize, const char *pFileName, int nLine) = 0;
  
      // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
      virtual void GlobalMemoryStatus(size_t *pUsedMemory, size_t *pFreeMemory) = 0;
  
      // Obtain virtual memory manager interface
      virtual IVirtualMemorySection *AllocateVirtualMemorySection(size_t numMaxBytes) = 0;
  
      // Request 'generic' memory stats (returns a list of N named values; caller should assume this list will change over time)
      virtual int GetGenericMemoryStats(GenericMemoryStat_t **ppMemoryStats) = 0;
  
      virtual ~IMemAlloc() {};
  
      // handles storing allocation info for coroutines
      virtual uint32 GetDebugInfoSize() = 0;
  
      virtual void SaveDebugInfo(void *pvDebugInfo) = 0;
  
      virtual void RestoreDebugInfo(const void *pvDebugInfo) = 0;
  
      virtual void InitDebugInfo(void *pvDebugInfo, const char *pchRootFileName, int nLine) = 0;
  };
  
  //-----------------------------------------------------------------------------
  // Singleton interface
  //-----------------------------------------------------------------------------
  #ifdef _PS3
  
  PLATFORM_INTERFACE IMemAlloc * g_pMemAllocInternalPS3;
  #ifndef PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
  #define g_pMemAlloc g_pMemAllocInternalPS3
  #else
  #define g_pMemAlloc PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
  #endif
  
  #else // !_PS3
  
  MEM_INTERFACE IMemAlloc *g_pMemAlloc;
  
  #endif
  
  //-----------------------------------------------------------------------------
  
  #ifdef MEMALLOC_REGIONS
  #ifndef MEMALLOC_REGION
  #define MEMALLOC_REGION 0
  #endif
  inline void *MemAlloc_Alloc( size_t nSize )
  { 
      return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
  }
  
  inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
  {
      return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
  }
  #else
  #undef MEMALLOC_REGION
  
  inline void *MemAlloc_Alloc(size_t nSize) {
      return g_pMemAlloc->IndirectAlloc(nSize);
  }
  
  inline void *MemAlloc_Alloc(size_t nSize, const char *pFileName, int nLine) {
      return g_pMemAlloc->IndirectAlloc(nSize, pFileName, nLine);
  }
  
  #endif
  
  //-----------------------------------------------------------------------------
  
  #ifdef MEMALLOC_REGIONS
  #else
  #endif
  
  
  inline bool ValueIsPowerOfTwo(size_t value)            // don't clash with mathlib definition
  {
      return (value & (value - 1)) == 0;
  }
  
  
  inline void *MemAlloc_AllocAlignedUnattributed(size_t size, size_t align) {
  #ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      unsigned char *pAlloc, *pResult;
  
  #endif
  
      if (!ValueIsPowerOfTwo(align))
          return NULL;
  
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      return g_pMemAlloc->AllocAlign( size, align );
  
  #else
  
      align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  
      if ((pAlloc = (unsigned char *) MemAlloc_Alloc(sizeof(void *) + align + size)) == (unsigned char *) NULL)
          return NULL;
  
      pResult = (unsigned char *) ((size_t) (pAlloc + sizeof(void *) + align) & ~align);
      ((unsigned char **) (pResult))[-1] = pAlloc;
  
      return (void *) pResult;
  
  #endif
  }
  
  inline void *MemAlloc_AllocAlignedFileLine(size_t size, size_t align, const char *pszFile, int nLine) {
  #ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      unsigned char *pAlloc, *pResult;
  
  #endif
  
      if (!ValueIsPowerOfTwo(align))
          return NULL;
  
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      return g_pMemAlloc->AllocAlign( size, align, pszFile, nLine );
  
  #else
  
      align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
  
      if ((pAlloc = (unsigned char *) MemAlloc_Alloc(sizeof(void *) + align + size, pszFile, nLine)) ==
          (unsigned char *) NULL)
          return NULL;
  
      pResult = (unsigned char *) ((size_t) (pAlloc + sizeof(void *) + align) & ~align);
      ((unsigned char **) (pResult))[-1] = pAlloc;
  
      return (void *) pResult;
  
  #endif
  }
  
  #ifdef USE_MEM_DEBUG
  #define MemAlloc_AllocAligned( s, a )	MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
  #elif defined(USE_LIGHT_MEM_DEBUG)
  extern const char *g_pszModule; 
  #define MemAlloc_AllocAligned( s, a )	MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
  #else
  #define MemAlloc_AllocAligned(s, a)    MemAlloc_AllocAlignedUnattributed( s, a )
  #endif
  
  
  inline void *MemAlloc_ReallocAligned(void *ptr, size_t size, size_t align) {
      if (!ValueIsPowerOfTwo(align))
          return NULL;
  
      // Don't change alignment between allocation + reallocation.
      if (((size_t) ptr & (align - 1)) != 0)
          return NULL;
  
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      return g_pMemAlloc->ReallocAlign( ptr, size, align );
  
  #else
  
      if (!ptr)
          return MemAlloc_AllocAligned(size, align);
  
      void *pAlloc, *pResult;
  
      // Figure out the actual allocation point
      pAlloc = ptr;
      pAlloc = (void *) (((size_t) pAlloc & ~(sizeof(void *) - 1)) - sizeof(void *));
      pAlloc = *((void **) pAlloc);
  
      // See if we have enough space
      size_t nOffset = (size_t) ptr - (size_t) pAlloc;
      size_t nOldSize = g_pMemAlloc->GetSize(pAlloc);
      if (nOldSize >= size + nOffset)
          return ptr;
  
      pResult = MemAlloc_AllocAligned(size, align);
      memcpy(pResult, ptr, nOldSize - nOffset);
      g_pMemAlloc->Free(pAlloc);
      return pResult;
  
  #endif
  }
  
  inline void MemAlloc_FreeAligned(void *pMemBlock) {
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      g_pMemAlloc->Free( pMemBlock );
  
  #else
  
      void *pAlloc;
  
      if (pMemBlock == NULL)
          return;
  
      pAlloc = pMemBlock;
  
      // pAlloc points to the pointer to starting of the memory block
      pAlloc = (void *) (((size_t) pAlloc & ~(sizeof(void *) - 1)) - sizeof(void *));
  
      // pAlloc is the pointer to the start of memory block
      pAlloc = *((void **) pAlloc);
  
      g_pMemAlloc->Free(pAlloc);
  
  #endif
  }
  
  inline void MemAlloc_FreeAligned(void *pMemBlock, const char *pszFile, int nLine) {
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      g_pMemAlloc->Free( pMemBlock, pszFile, nLine );
  
  #else
  
      void *pAlloc;
  
      if (pMemBlock == NULL)
          return;
  
      pAlloc = pMemBlock;
  
      // pAlloc points to the pointer to starting of the memory block
      pAlloc = (void *) (((size_t) pAlloc & ~(sizeof(void *) - 1)) - sizeof(void *));
  
      // pAlloc is the pointer to the start of memory block
      pAlloc = *((void **) pAlloc);
      g_pMemAlloc->Free(pAlloc, pszFile, nLine);
  
  #endif
  }
  
  inline size_t MemAlloc_GetSizeAligned(void *pMemBlock) {
  #ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
  
      return g_pMemAlloc->GetSize( pMemBlock );
  
  #else
  
      void *pAlloc;
  
      if (pMemBlock == NULL)
          return 0;
  
      pAlloc = pMemBlock;
  
      // pAlloc points to the pointer to starting of the memory block
      pAlloc = (void *) (((size_t) pAlloc & ~(sizeof(void *) - 1)) - sizeof(void *));
  
      // pAlloc is the pointer to the start of memory block
      pAlloc = *((void **) pAlloc);
      return g_pMemAlloc->GetSize(pAlloc) - ((::byte *) pMemBlock - (::byte *) pAlloc);
  
  #endif
  }
  
  
  struct aligned_tmp_t {
      // empty base class
  };
  
  // template here to allow adding alignment at levels of hierarchy that aren't the base
  template<int bytesAlignment = 16, class T = aligned_tmp_t>
  class CAlignedNewDelete : public T {
  public:
      void *operator new(size_t nSize) {
          return MemAlloc_AllocAligned(nSize, bytesAlignment);
      }
  
      void *operator new(size_t nSize, int nBlockUse, const char *pFileName, int nLine) {
          return MemAlloc_AllocAlignedFileLine(nSize, bytesAlignment, pFileName, nLine);
      }
  
      void operator delete(void *pData) {
          if (pData) {
              MemAlloc_FreeAligned(pData);
          }
      }
  
      void operator delete(void *pData, int nBlockUse, const char *pFileName, int nLine) {
          if (pData) {
              MemAlloc_FreeAligned(pData, pFileName, nLine);
          }
      }
  };
  
  //-----------------------------------------------------------------------------
  
  #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  #define MEM_ALLOC_CREDIT_(tag)	CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ )
  #define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
  #define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
  #define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  #define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
  #else
  #define MEM_ALLOC_CREDIT_(tag)    ((void)0)
  #define MemAlloc_PushAllocDbgInfo(pszFile, line) ((void)0)
  #define MemAlloc_PopAllocDbgInfo() ((void)0)
  #define MemAlloc_RegisterAllocation(pFileName, nLine, nLogicalSize, nActualSize, nTime) ((void)0)
  #define MemAlloc_RegisterDeallocation(pFileName, nLine, nLogicalSize, nActualSize, nTime) ((void)0)
  #endif
  
  //-----------------------------------------------------------------------------
  
  class CMemAllocAttributeAlloction {
  public:
      CMemAllocAttributeAlloction(const char *pszFile, int line) {
          MemAlloc_PushAllocDbgInfo(pszFile, line);
      }
  
      ~CMemAllocAttributeAlloction() {
          MemAlloc_PopAllocDbgInfo();
      }
  };
  
  #define MEM_ALLOC_CREDIT()    MEM_ALLOC_CREDIT_(__FILE__)
  
  //-----------------------------------------------------------------------------
  
  #if defined(MSVC) && (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  
  #pragma warning(disable:4290)
  #pragma warning(push)
  #include <typeinfo>
  
  // MEM_DEBUG_CLASSNAME is opt-in.
  // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
  // simultaneously, it'll need a mutex.
  #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
  
      template <typename T> const char *MemAllocClassName( T *p )
      {
          static const char *pszName = typeid(*p).name(); // @TODO: support having debug heap ignore certain allocations, and ignore memory allocated here [5/7/2009 tom]
          return pszName;
      }
  
  #define MEM_ALLOC_CREDIT_CLASS()	MEM_ALLOC_CREDIT_( MemAllocClassName( this ) )
  #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
  #else
  #define MEM_ALLOC_CREDIT_CLASS()	MEM_ALLOC_CREDIT_( __FILE__ )
  #define MEM_ALLOC_CLASSNAME(type) (__FILE__)
  #endif
  
  // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
  #ifdef _MSC_VER
  #define MEM_ALLOC_CREDIT_FUNCTION()		MEM_ALLOC_CREDIT_( __FUNCTION__ )
  #else
  #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
  #endif
  
  #pragma warning(pop)
  #else
  #define MEM_ALLOC_CREDIT_CLASS()
  #define MEM_ALLOC_CLASSNAME(type) NULL
  #define MEM_ALLOC_CREDIT_FUNCTION()
  #endif
  
  //-----------------------------------------------------------------------------
  
  #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  struct MemAllocFileLine_t
  {
      const char *pszFile;
      int line;
  };
  
  #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
      static CUtlMap<void *, MemAllocFileLine_t, int> s_##tag##Allocs( DefLessFunc( void *) ); \
      CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs = &s_##tag##Allocs; \
      static CThreadFastMutex s_##tag##AllocsMutex; \
      CThreadFastMutex * g_p##tag##AllocsMutex = &s_##tag##AllocsMutex; \
      const char * g_psz##tag##Alloc = strcpy( (char *)MemAlloc_Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
  
  #define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag ) \
      extern CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs; \
      extern CThreadFastMutex *g_p##tag##AllocsMutex; \
      extern const char * g_psz##tag##Alloc;
  
  #define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
      if ( !p ) \
          ; \
      else \
      { \
          AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
          MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
          g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
          if ( fileLine.pszFile != g_psz##tag##Alloc ) \
          { \
              g_p##tag##Allocs->Insert( p, fileLine ); \
          } \
          \
          MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
      }
  
  #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
      if ( !p ) \
          ; \
      else \
      { \
          AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
          MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
          CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_p##tag##Allocs->Find( p ); \
          if ( iRecordedFileLine != g_p##tag##Allocs->InvalidIndex() ) \
          { \
              fileLine = (*g_p##tag##Allocs)[iRecordedFileLine]; \
              g_p##tag##Allocs->RemoveAt( iRecordedFileLine ); \
          } \
          \
          MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
      }
  
  #else
  
  #define MEMALLOC_DEFINE_EXTERNAL_TRACKING(tag)
  #define MEMALLOC_DECLARE_EXTERNAL_TRACKING(tag)
  #define MemAlloc_RegisterExternalAllocation(tag, p, size) ((void)0)
  #define MemAlloc_RegisterExternalDeallocation(tag, p, size) ((void)0)
  
  #endif
  
  //-----------------------------------------------------------------------------
  
  #endif // !STEAM && !NO_MALLOC_OVERRIDE
  
  //-----------------------------------------------------------------------------
  
  #if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
  #include <malloc.h>
  
  #define MEM_ALLOC_CREDIT_(tag)	((void)0)
  #define MEM_ALLOC_CREDIT()	MEM_ALLOC_CREDIT_(__FILE__)
  #define MEM_ALLOC_CREDIT_CLASS()
  #define MEM_ALLOC_CLASSNAME(type) NULL
  
  #define MemAlloc_PushAllocDbgInfo( pszFile, line )
  #define MemAlloc_PopAllocDbgInfo()
  
  #define MemAlloc_RegisterAllocation( a,b,c,d,e ) ((void)0)
  #define MemAlloc_RegisterDeallocation( a,b,c,d,e ) ((void)0)
  
  #define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
  #define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
  #define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
  
  inline void *MemAlloc_AllocAligned( size_t size, size_t align )
  {
      return (void *)_aligned_malloc( size, align );
  }
  inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
  {
      pszFile = pszFile;
      nLine = nLine;
      return (void *)_aligned_malloc( size, align );
  }
  
  inline void MemAlloc_FreeAligned( void *pMemBlock )
  {
      _aligned_free( pMemBlock );
  }
  inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
  {
      pszFile = pszFile;
      nLine = nLine;
      _aligned_free( pMemBlock );
  }
  
  #endif // !STEAM && NO_MALLOC_OVERRIDE
  
  //-----------------------------------------------------------------------------
  
  
  
  // linux memory tracking via hooks.
  #if defined( POSIX ) && !defined( _PS3 )
  PLATFORM_INTERFACE void MemoryLogMessage( char const *s );						// throw a message into the memory log
  PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
  PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
  PLATFORM_INTERFACE void DumpMemorySummary( void );
  PLATFORM_INTERFACE void SetMemoryMark( void );
  PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
  
  // ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
  PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
  #else
  
  inline void MemoryLogMessage(char const *) {
  }
  
  inline void EnableMemoryLogging(bool) {
  }
  
  inline void DumpMemoryLog(int) {
  }
  
  inline void DumpMemorySummary(void) {
  }
  
  inline void SetMemoryMark(void) {
  }
  
  inline void DumpChangedMemory(int) {
  }
  
  inline size_t ApproximateProcessMemoryUsage(void) {
      return 0;
  }
  
  #endif
  
  
  #endif /* TIER0_MEMALLOC_H */
  