home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / rvHeap.h < prev    next >
C/C++ Source or Header  |  2005-11-14  |  18KB  |  378 lines

  1. //
  2. // rvHeap.h - Heap object (replacing the idHeap class)
  3. // Date: 12/13/04
  4. // Created by: Dwight Luetscher
  5. //
  6.  
  7. #ifndef __RV_HEAP_H__
  8. #define __RV_HEAP_H__
  9.  
  10. class rvHeapArena;
  11. struct rvMemoryBlock_s;
  12. struct rvFreeMemoryBlock_s;
  13.  
  14. //#define _DETECT_BLOCK_MERGE_PROBLEMS
  15.  
  16. // Define some flags used in describing various properties of allocations 
  17. // coming from this heap (these flags are passed into rvHeap::Init()).
  18. static const uint rvHeapFlagDefault                = 0;
  19. static const uint rvHeapFlagWriteCombine        = 0x0001;    // flag specified if the memory allocated from this heap is intended to have a write-combine cache policy
  20. static const uint rvHeapFlagNoCache                = 0x0002;    // flag specified if the memory allocated from this heap is intended to have a no cache policy
  21.  
  22. // Define some limits used by each heap 
  23. static const uint NUM_MEMORY_BLOCK_SIZE_BITS    = 27;
  24. static const uint NUM_TAG_BITS                    = 5;
  25.  
  26. static const uint MAX_SINGLE_ALLOCATION_SIZE    = ((1 << (NUM_MEMORY_BLOCK_SIZE_BITS+2)) - 1);    // maximum number of bytes that can be allocated in a single allocation
  27. static const uint NUM_SMALL_BLOCK_TABLE_ENTRIES    = 2048;                    // number of entries within each heap's small free memory block table
  28.  
  29. static const uint SMALL_BLOCK_ALIGN_SIZE_SHIFT    = 2;                    // left shift of the size that all allocations are rounded to
  30. static const uint SMALL_BLOCK_ALIGN_SIZE        = 1 << SMALL_BLOCK_ALIGN_SIZE_SHIFT;    // size that all allocations are rounded to
  31. static const uint SMALL_BLOCK_ALIGN_SIZE_MASK    = SMALL_BLOCK_ALIGN_SIZE-1;                // mask of the bits used for the size that all allocations are rounded to
  32. static const uint MAX_SMALL_BLOCK_SIZE            = (NUM_SMALL_BLOCK_TABLE_ENTRIES << SMALL_BLOCK_ALIGN_SIZE_SHIFT) - 1;    // maximum size of an allocation to be considered a "small block" allocation
  33.  
  34. static const uint PAGE_SIZE_SHIFT                = 16;                    // left shift of the page size used by this heap object
  35. static const uint PAGE_SIZE                        = 1 << PAGE_SIZE_SHIFT;    // page size used by this heap object
  36. static const uint PAGE_SIZE_MASK                = PAGE_SIZE - 1;
  37.  
  38. static const uint MAX_SMALL_PAGE_RANGE            = 128;                        // maximum number of contiguous pages for a single range to be considered "small"
  39. static const uint MIN_LARGE_PAGE_RANGE            = MAX_SMALL_PAGE_RANGE+1;    // minimum number of contiguous pages for a single range to be considered "large"
  40.  
  41. // Define the freePageRange_t structure used by this rvHeap used to maintain linked-lists of contiguous page ranges below LARGE_PAGE_RANGE
  42. typedef struct freePageRange_s
  43. {
  44.     freePageRange_s* m_nextFree;                        // next range of free pages in a linked-list
  45. }
  46. freePageRange_t;
  47.  
  48. // Define the freePageRange_t structure used by this rvHeap used to maintain a linked-list of contiguous page ranges above LARGE_PAGE_RANGE
  49. typedef struct freeLargePageRange_s
  50. {
  51.     freeLargePageRange_s* m_nextFree;                    // next large range of free pages in a linked-list
  52.     uint m_firstPageOffset;                                // offset of the first page in this range
  53.     uint m_numContiguousPages;                            // count of the number of contiguous pages in this range
  54. }
  55. freeLargePageRange_t;
  56.  
  57. class rvHeap 
  58. {
  59. public:
  60.     rvHeap( );                                            // constructor
  61.     ~rvHeap( );                                            // destructor
  62.  
  63.     void Init( rvHeapArena &heapArena, uint maxHeapSizeBytes, uint flags = rvHeapFlagDefault );    // initializes this heap for use within the given arena, and with the given size limit that it can grow to 
  64.     void Shutdown( );                                    // releases this heap from use
  65.  
  66.     ID_INLINE bool IsInitialized( ) const;                // returns true if this heap is currently initialized, and not shutdown
  67.     
  68.     ID_INLINE void *Allocate( uint sizeBytes, int debugTag = 0 );    // allocate memory
  69.     ID_INLINE void *Allocate16( uint sizeBytes, int debugTag = 0 );    // allocate memory aligned on a 16-byte boundary
  70.     void Free( void *allocation );                        // free memory 
  71.  
  72.     int Msize( void *allocation );                        // returns the size, in bytes, of the allocation at the given address (including header, alignment bytes, etc).
  73.  
  74.     void FreeAll( );                                    // frees all the allocations from this heap (and decommits all pages)
  75.  
  76.     ID_INLINE bool DoesAllocBelong( void  *allocBase );    // returns true if the given address was allocated from this heap, false otherwise
  77.  
  78.     ID_INLINE rvHeapArena *GetArena( );                    // returns the arena this heap is associated with
  79.  
  80.     ID_INLINE void PushCurrent( );                        // makes this heap the new top of stack for its associated arena, thus making it current
  81.     ID_INLINE void PopCurrent( );                        // pops this heap, or any other heap, from the top of stack of this heap's associated arena, thus making its predecessor current
  82.  
  83.     ID_INLINE uint GetSize( ) const;                    // returns the current size that this heap has grown to, in bytes
  84.     ID_INLINE uint GetMaxSize( ) const;                    // returns the maximum size that this heap can grow to, in bytes
  85.  
  86.     ID_INLINE uint GetCommittedSize( ) const;            // returns the number of physical bytes this heap is currently using (total bytes of all committed pages)
  87.     ID_INLINE uint GetBytesAllocated( ) const;            // returns the number of bytes currently allocated from this heap (actual memory footprint of all active allocations including internal headers and alignment bytes)
  88.     ID_INLINE uint GetBytesRequested( ) const;
  89.     ID_INLINE int GetNumAllocations( ) const;            // returns the number of allocations made from this heap that are still active (have not been freed)
  90.  
  91.     ID_INLINE uint GetBytesAllocatedByTag( Mem_Alloc_Types_t allocType ) const;        // returns the number of bytes currently allocated from this heap with the given allocation tag (actual memory footprint of all active allocations including internal headers and alignment bytes)
  92.     ID_INLINE uint GetPeekBytesAllocatedByTag( Mem_Alloc_Types_t allocType ) const;    // returns the peek number of bytes allocated from this heap with the given allocation tag (actual memory footprint of all active allocations including internal headers and alignment bytes)
  93.     ID_INLINE int GetNumAllocationsByTag( Mem_Alloc_Types_t allocType ) const;        // returns the current number of allocation from this heap with the given allocation tag 
  94.  
  95.     ID_INLINE bool IsWriteCombine( ) const;                // returns true if memory allocated from this heap has a write-combine cache policy, false otherwise
  96.     ID_INLINE bool IsNoCache( ) const;                    // returns true if memory allocated from this heap has a no-cache policy, false otherwise
  97.  
  98.     int SmallBlockCount() const { return NUM_SMALL_BLOCK_TABLE_ENTRIES; }
  99.     int GetSmallBlockFreeCount( int block ) const;
  100.     dword GetSmallBlockFreeSize( int block ) const;
  101.     
  102.     int GetLargeBlockFreeCount() const;
  103.     dword GetLargeBlockFreeSize() const;
  104.  
  105.     int GetBlockFreeCount( rvFreeMemoryBlock_s* currentBlock ) const;
  106.     dword GetBlockFreeSize( rvFreeMemoryBlock_s* currentBlock ) const;
  107.  
  108.     void SetName(const char* name);
  109.     const char* GetName(void) const;
  110.     void SetDebugID(byte debugID) {mDebugID=debugID;}
  111.     byte DebugID(void) const {return mDebugID;}
  112.  
  113. protected:
  114.     rvHeapArena *m_arena;                                // arena associated with this heap
  115.     rvHeap *m_next;                                        // next heap belonging to the same arena
  116.     CRITICAL_SECTION m_criticalSection;                    // critical section associated with this heap
  117.  
  118.     byte *m_baseAddress;                                // base address of this heap (virtual)
  119.     byte *m_zeroLengthAllocPage;                        // special page for zero-length allocations (remains uncommitted) 
  120.     byte *m_heapStorageStart;                            // address of the start of this heap's storage (just past page table)
  121.  
  122.     rvFreeMemoryBlock_s *m_smallFreeBlocks[NUM_SMALL_BLOCK_TABLE_ENTRIES];    // table used to manage linked-lists of small free memory blocks
  123.     rvFreeMemoryBlock_s *m_largeFreeBlocks;                // linked-list of all of the large free memory blocks
  124.  
  125.     dword *m_pageCommitStateTable;                        // a very long bit mask (1-bit per page) that describes whether the page has been committed or not to physical memory
  126.     freePageRange_t *m_smallFreePageRangeTable;            // array of structures that each correspond to a particular page - the structures representing the pages at the start of a small range are added to lists within the m_smallFreePageRangeLists[] array below
  127.  
  128.     freePageRange_t *m_smallFreePageRangeLists[MAX_SMALL_PAGE_RANGE];        // array where each entry is a linked-list of structures that individually describe a contiguous range of pages (where the range count matches the index into this array plus 1)
  129.     freeLargePageRange_t *m_largeFreePageRangeList;        // linked-list of structures that individually describe a large contiguous range of pages
  130.  
  131.     // the following two data members are just used to manage the storage of the freeLargePageRange_t structures
  132.     freeLargePageRange_t *m_largeFreeRangeReuseList;    // linked-list of freeLargePageRange_t that are currently not part of the m_largeFreePageRangeList linked-list and are available for use
  133.     freeLargePageRange_t *m_largeFreeRangeStorage;        // array that acts as a store of the freeLargePageRange_t structures
  134.     uint m_largeFreeRangeStorageSize;                    // number of entries in the m_largeFreeRangeStorage[] array
  135.     uint m_pageCommitStateArrayByteSize;                // size of the m_pageCommitStateTable[] array in bytes
  136.     uint m_smallFreePageRangeByteSize;                    // size of the m_smallFreePageRangeTable[] array in bytes
  137.  
  138.     uint m_numPages;                                    // number of pages that can span this heap entirely
  139.  
  140.     uint m_heapRangeBytes;                                // the number of bytes in the virtual address space of this heap (including zero-length allocation page)
  141.  
  142.     uint m_committedSizeBytes;                            // the number of physical bytes this heap is currently using (total bytes of all committed pages)
  143.     uint m_maxHeapSizeBytes;                            // the maximum size that this heap can grow to, in bytes (allocatable space)
  144.  
  145.     uint m_numBytesRequested;                            // the number of bytes currently requested for allocation from this heap (memory footprint without the overhaed of internal headers and alignment bytes)
  146.     uint m_numBytesAllocated;                            // the number of bytes currently allocated from this heap (actual memory footprint of all active allocations including internal headers and alignment bytes)
  147.  
  148.     uint m_allocatedBytesByTag[MA_MAX];                    // the number of bytes allocated from this heap - organized by usage tag
  149.     uint m_peekAllocatedBytesByTag[MA_MAX];                // the peek number of bytes allocated from this heap - organized by usage tag
  150.     int m_numAllocationsByTag[MA_MAX];                    // the number of allocations - organized by usage tag
  151.  
  152.     int m_numAllocations;                                // the number of allocations made from this heap that are still active (have not been freed)
  153.     int m_numZeroLengthAllocations;                        // the number of zero length allocations made from this heap
  154.  
  155.     uint m_largestFreeSmallBlockOffset;                    // small block table offset of the largest free small block available (block that is part of m_smallFreeBlocks[] table)
  156.  
  157.     uint m_flags;                                        // flags that describe various properties of this heap
  158.  
  159.     byte mDebugID;                                        // ID that identifies heap. Needed to absolutely identify a heap.
  160.     char m_name[20];                                    // for debug display
  161.  
  162.     void ResetValues( );                                // resets the data members to their pre-initialized state
  163.  
  164.     void BuildLargeFreeRangeReuseList( );                // builds the m_largeFreeRangeReuseList linked-list from the m_largeFreeRangeStorage[] array.
  165.  
  166.     byte *AllocateMemory( uint sizeBytes, int debugTag, bool align16Flag );    // performs memory allocation for the given number of bytes from this heap
  167.  
  168.     rvMemoryBlock_s *AllocateMemorySmallBlock( uint sizeBytes );    // perform a small block allocation - try to use an existing free block pointed to by the table.
  169.     rvMemoryBlock_s *AllocateBlockFromTable( uint smallBlockTableOffset, uint sizeBytes );    // allocates the a small memory block from the free block table and partitions it, if necessary, into an allocated chunk and a free chunk (which remains in the m_smallFreeBlocks[] table).
  170.     rvMemoryBlock_s *AllocateMemoryLargeBlock( uint sizeBytes );    // perform a large block allocation - try to use an existing free block from within the large free block linked-list.
  171.  
  172.     void TestLargestFreeSmallBlockOffset( uint smallBlockTableOffset );    // checks to see if the largest free small block has moved down
  173.  
  174.     void FixUpNextBlocksPrev( byte *newBlock, uint blockSize );    // fixes up the previous pointer of the memory block that lies immediately past the given newBlock, if it remains on the same page.
  175.  
  176.     void AddFreeBlock( rvFreeMemoryBlock_s *freeBlock );    // adds the given free block to the small allocation table or large allocation list.
  177.     void RemoveFreeBlock( rvFreeMemoryBlock_s *freeBlock );    // removes the given block from the small allocation table or large allocation list.
  178.  
  179.     void *PageCommit( uint numDesiredPages );                // commits the given number of contiguous pages to physical memory 
  180.     void PageUncommit( byte *pageAddress, uint numPages );    // uncommits the given range of contiguous pages back to physical memory
  181.  
  182.     void RemoveFromSmallFreeRangeList( uint pageOffset, uint freeBlockPageCount );                    // removes the given page range from the m_smallFreePageRangeLists[]
  183.     void RemoveFromLargeFreeRangeList( uint pageOffset, uint &startPageOffset, uint &pageCount );    // removes the given page range from the m_largeFreePageRangeList
  184.  
  185.     void *CommitPageRange( uint startPageOffset, uint numPages );    // commits the given range of pages and flags them as committed within the m_pageCommitStateTable array
  186.     void UncommitPageRange( uint startPageOffset, uint numPages );    // uncommits the given range of pages and clears their flags within the m_pageCommitStateTable array
  187.  
  188.     void EnterHeapCriticalSection();                    // enters this heap's critical section
  189.     void ExitHeapCriticalSection();                        // exits this heap's critical section
  190.  
  191. #ifdef _DETECT_BLOCK_MERGE_PROBLEMS
  192.     void TestFreeBlockValidity();                        // test for free memory block merge problems
  193. #endif
  194.  
  195.     friend class rvHeapArena;                            // give the rvHeapArena class access to the following methods
  196.     // {
  197.     ID_INLINE void SetArena( rvHeapArena *arena );        // sets the arena this heap is associated with
  198.     ID_INLINE void SetNext( rvHeap *next );                // sets the next heap associated with the same arena
  199.     ID_INLINE rvHeap *GetNext( );                        // returns the next heap associated with the same arena
  200.     // }
  201. };
  202.  
  203. // IsInitialized
  204. // 
  205. // returns: true if this heap is currently initialized, and not shutdown
  206. ID_INLINE bool rvHeap::IsInitialized( ) const
  207. {
  208.     return m_arena != NULL;
  209. }
  210.  
  211. // Allocate
  212. // 
  213. // allocate memory
  214. void *rvHeap::Allocate( uint sizeBytes, int debugTag )
  215. {
  216.     return AllocateMemory( sizeBytes, debugTag, false );
  217. }
  218.  
  219. // Allocate16
  220. //
  221. // allocate memory aligned on a 16-byte boundary
  222. void *rvHeap::Allocate16( uint sizeBytes, int debugTag )
  223. {
  224.     return AllocateMemory( sizeBytes, debugTag, true );
  225. }
  226.  
  227. // DoesAllocBelong
  228. //
  229. // returns: true if the given address was allocated from this heap, false otherwise
  230. ID_INLINE bool rvHeap::DoesAllocBelong( void  *allocBase )
  231. {
  232.     return allocBase >= m_zeroLengthAllocPage && allocBase < m_heapStorageStart + m_heapRangeBytes;
  233. }
  234.  
  235. // GetArena
  236. //
  237. // returns: the arena this heap is associated with
  238. ID_INLINE rvHeapArena *rvHeap::GetArena( )
  239. {
  240.     return m_arena;
  241. }
  242.  
  243. // GetNext
  244. //
  245. // returns: the next heap belonging to the same arena
  246. ID_INLINE rvHeap *rvHeap::GetNext( )
  247. {
  248.     return m_next;
  249. }
  250.  
  251. // PushCurrent
  252. //  
  253. // makes this heap the new top of stack for its associated arena, thus making it current.
  254. ID_INLINE void rvHeap::PushCurrent( )
  255. {
  256.     m_arena->Push( *this );
  257. }
  258.  
  259. // PopCurrent
  260. //
  261. // pops this heap, or any other heap, from the top of stack of this heap's associated arena, 
  262. // thus making its predecessor current
  263. ID_INLINE void rvHeap::PopCurrent( )
  264. {
  265.     m_arena->Pop( );
  266. }
  267.  
  268. // GetCommittedSize
  269. //
  270. // returns: the number of physical bytes this heap is currently using (total bytes of all committed pages)
  271. ID_INLINE uint rvHeap::GetCommittedSize( ) const
  272. {
  273.     return m_committedSizeBytes;
  274. }
  275.  
  276. // GetMaxSize
  277. // 
  278. // returns the maximum size that this heap can grow to, in bytes
  279. ID_INLINE uint rvHeap::GetMaxSize( ) const
  280. {
  281.     return m_maxHeapSizeBytes;
  282. }
  283.  
  284. // GetBytesAllocated
  285. //
  286. // returns: the number of bytes currently allocated from this heap 
  287. //            (actual memory footprint of all active allocations 
  288. //            including internal headers and alignment bytes)
  289. //
  290. ID_INLINE uint rvHeap::GetBytesAllocated( ) const
  291. {
  292.     return m_numBytesAllocated;
  293. }
  294.  
  295. // GetBytesRequested
  296. //
  297. // returns: the number of bytes currently requested from this heap
  298. //            (i.e. without overhead)
  299. //
  300. ID_INLINE uint rvHeap::GetBytesRequested( ) const
  301. {
  302.     return m_numBytesRequested;
  303. }
  304.  
  305. // GetNumAllocations
  306. //
  307. // returns: the number of allocations made from this heap that are still active (have not been freed)
  308. ID_INLINE int rvHeap::GetNumAllocations( ) const
  309. {
  310.     return m_numAllocations;
  311. }
  312.  
  313. // GetBytesAllocatedByTag
  314. //
  315. // returns: the number of bytes currently allocated from this heap with the given allocation tag 
  316. //            (actual memory footprint of all active allocations including internal headers and 
  317. //            alignment bytes).
  318. ID_INLINE uint rvHeap::GetBytesAllocatedByTag( Mem_Alloc_Types_t allocType ) const
  319. {
  320.     assert( allocType < MA_MAX );
  321.     return m_allocatedBytesByTag[(uint) allocType];
  322. }
  323.  
  324. // GetPeekBytesAllocatedByTag
  325. //
  326. // returns: the peek number of bytes allocated from this heap with the given allocation tag (actual 
  327. //            memory footprint of all active allocations including internal headers and alignment bytes)
  328. ID_INLINE uint rvHeap::GetPeekBytesAllocatedByTag( Mem_Alloc_Types_t allocType ) const
  329. {
  330.     assert( allocType < MA_MAX );
  331.     return m_peekAllocatedBytesByTag[(uint) allocType];
  332. }
  333.  
  334. // GetNumAllocationsByTag
  335. // 
  336. // returns: the current number of allocation from this heap with the given allocation tag 
  337. ID_INLINE int rvHeap::GetNumAllocationsByTag( Mem_Alloc_Types_t allocType ) const
  338. {
  339.     assert( allocType < MA_MAX );
  340.     return m_numAllocationsByTag[(uint) allocType];
  341. }
  342.  
  343. // IsWriteCombine
  344. //
  345. // returns: true if memory allocated from this heap has a write-combine cache policy, false otherwise
  346. ID_INLINE bool rvHeap::IsWriteCombine( ) const
  347. {
  348.     return (m_flags & rvHeapFlagWriteCombine) != 0;
  349. }
  350.  
  351. // IsNoCache
  352. //
  353. // returns: true if memory allocated from this heap has a no-cache policy, false otherwise
  354. ID_INLINE bool rvHeap::IsNoCache( ) const
  355. {
  356.     return (m_flags & rvHeapFlagNoCache) != 0;
  357. }
  358.  
  359. // SetArena
  360. //
  361. // sets the arena this heap is associated with
  362. ID_INLINE void rvHeap::SetArena( rvHeapArena *arena )
  363. {
  364.     m_arena = arena;
  365. }
  366.  
  367. // SetNext
  368. // 
  369. // sets the next heap associated with the same arena
  370. ID_INLINE void rvHeap::SetNext( rvHeap *next )
  371. {
  372.     m_next = next;
  373. }
  374.  
  375. extern void Mem_FragmentationStats_f( const class idCmdArgs &args );
  376.  
  377. #endif    // #ifndef __RV_HEAP_H__
  378.