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.
304 lines
10 KiB
304 lines
10 KiB
#ifndef _HEAP_HPP_
|
|
#define _HEAP_HPP_
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'hpp' files for this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants exported from the class. */
|
|
/* 3. Data structures exported from the class. */
|
|
/* 4. Forward references to other data structures. */
|
|
/* 5. Class specifications (including inline functions). */
|
|
/* 6. Additional large inline functions. */
|
|
/* */
|
|
/* Any portion that is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "Global.hpp"
|
|
|
|
#include "Environment.hpp"
|
|
#include "Common.hpp"
|
|
#include "Find.hpp"
|
|
#include "NewPage.hpp"
|
|
#include "Prefetch.hpp"
|
|
#include "Rockall.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class forward references. */
|
|
/* */
|
|
/* We need to refer to the following classes before they are */
|
|
/* fully specified so here we list them as forward references. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
class BUCKET;
|
|
class CACHE;
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The heap interface. */
|
|
/* */
|
|
/* The traditional memory allocation interface only supports */
|
|
/* a single allocation heap. This memory allocator supports */
|
|
/* multiple allocation heaps. However, the interface nicely */
|
|
/* hides this so at this point we are back to the traditional */
|
|
/* single heap interface. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
class HEAP : public ENVIRONMENT, public COMMON
|
|
{
|
|
//
|
|
// Private data.
|
|
//
|
|
// The heap is the top level container of all the
|
|
// functionality in the other classes. The 'Active'
|
|
// flag indicates if the heap has been initialized.
|
|
// The 'MaxFreePages' controls the amount of free
|
|
// space the heap will slave before it starts to
|
|
// return it the the external allocator. The
|
|
// 'SmallestParentMask' is mask that shows which
|
|
// parts of an address can be safely masked off
|
|
// and still ensure a hit in the find lookaside
|
|
// cache. The 'ThreadSafe' flag indicates whether
|
|
// locking being used.
|
|
//
|
|
BOOLEAN Active;
|
|
SBIT32 MaxFreePages;
|
|
BIT32 SmallestParentMask;
|
|
BOOLEAN ThreadSafe;
|
|
|
|
//
|
|
// A heap is merely a collection of fixed sized
|
|
// allocation buckets (each with an optional cache).
|
|
// The 'CachesSize' is the total number of buckets.
|
|
// The 'MinCacheSize' is the allocation size of the
|
|
// smallest bucket. The 'MidCacheSize' is the size
|
|
// of the bucket where the stride changes. The
|
|
// 'MaxCacheSize' is the allocation size of the
|
|
// largest bucket externally visable.
|
|
//
|
|
SBIT32 CachesSize;
|
|
SBIT32 MinCacheSize;
|
|
SBIT32 MidCacheSize;
|
|
SBIT32 MaxCacheSize;
|
|
|
|
//
|
|
// A key function of the heap is to convert the
|
|
// requested allocation size into a pointer to
|
|
// the appropriate bucket (and cache). This has
|
|
// to be very fast and is achieved using a direct
|
|
// lookup (i.e. an array). The lookup array
|
|
// consists of two sections (i.e. for small sizes
|
|
// and large sizes) to minimize space. The
|
|
// 'MaxTable1' and 'MaxTable2' variables contain
|
|
// the size of each section of the array. The
|
|
// 'ShiftSize1' and 'ShiftSize2' variables contain
|
|
// the shift that should be applied to the size to
|
|
// obtain the appropriate index. The 'SizeToCache1'
|
|
// and 'SizeToCache2' pointers refer to the direct
|
|
// lookup tables.
|
|
//
|
|
SBIT32 MaxTable1;
|
|
SBIT32 MaxTable2;
|
|
SBIT32 ShiftSize1;
|
|
SBIT32 ShiftSize2;
|
|
CACHE **SizeToCache1;
|
|
CACHE **SizeToCache2;
|
|
|
|
//
|
|
// The heap needs to have access to most of the
|
|
// other classes. The 'Caches' class sits on
|
|
// top of an allocation bucket which owns all
|
|
// the allocated memory for a given size. The
|
|
// 'ExternalCache' is a special bucket that
|
|
// contains weird sized pages. The 'Find' class
|
|
// translates allocation addresses to page
|
|
// descriptions. The 'Rockall' class is needed
|
|
// to gain access to the external allocation APIs.
|
|
// The 'NewPage' class owns all page descriptions
|
|
// and plays a significant role in whole heap
|
|
// operations. The 'TopCache' is the largest
|
|
// bucket size and owns almost all the externally
|
|
// allocated memory.
|
|
//
|
|
CACHE **Caches;
|
|
CACHE *ExternalCache;
|
|
FIND *Find;
|
|
NEW_PAGE *NewPage;
|
|
PREFETCH Prefetch;
|
|
ROCKALL *Rockall;
|
|
CACHE *TopCache;
|
|
#ifdef ENABLE_HEAP_STATISTICS
|
|
|
|
//
|
|
// Statistics data.
|
|
//
|
|
// A key feature of this heap is its ability to be
|
|
// significantly reconfigured at run time. A great
|
|
// deal of complexity could have been removed if
|
|
// certain static choices had been made. Although
|
|
// this flexibility is nice the support of statistics
|
|
// here allows precise information to be collected so
|
|
// to enable the value of this to be maximized.
|
|
//
|
|
//
|
|
SBIT32 CopyMisses;
|
|
SBIT32 MaxCopySize;
|
|
SBIT32 MaxNewSize;
|
|
SBIT32 NewMisses;
|
|
SBIT32 Reallocations;
|
|
SBIT32 *Statistics;
|
|
SBIT32 TotalCopySize;
|
|
SBIT32 TotalNewSize;
|
|
#endif
|
|
|
|
public:
|
|
//
|
|
// Public functions.
|
|
//
|
|
// The heap exports the high level interface
|
|
// out to the world. Any request a developer
|
|
// can make must come through one of these
|
|
// functions.
|
|
//
|
|
HEAP
|
|
(
|
|
CACHE *Caches1[],
|
|
CACHE *Caches2[],
|
|
SBIT32 MaxFreeSpace,
|
|
FIND *NewFind,
|
|
NEW_PAGE *NewPages,
|
|
ROCKALL *NewRockall,
|
|
SBIT32 Size1,
|
|
SBIT32 Size2,
|
|
SBIT32 Stride1,
|
|
SBIT32 Stride2,
|
|
BOOLEAN NewThredSafe
|
|
);
|
|
|
|
BOOLEAN Delete( VOID *Address,SBIT32 Size = NoSize );
|
|
|
|
VOID DeleteAll( BOOLEAN Recycle = True );
|
|
|
|
BOOLEAN Details( VOID *Address,SBIT32 *Size = NULL );
|
|
|
|
VOID LockAll( VOID );
|
|
|
|
BOOLEAN MultipleDelete
|
|
(
|
|
SBIT32 Actual,
|
|
VOID *Array[],
|
|
SBIT32 Size = NoSize
|
|
);
|
|
|
|
BOOLEAN MultipleNew
|
|
(
|
|
SBIT32 *Actual,
|
|
VOID *Array[],
|
|
SBIT32 Requested,
|
|
SBIT32 Size,
|
|
SBIT32 *Space = NULL,
|
|
BOOLEAN Zero = False
|
|
);
|
|
|
|
VOID *New
|
|
(
|
|
SBIT32 Size,
|
|
SBIT32 *Space = NULL,
|
|
BOOLEAN Zero = False
|
|
);
|
|
|
|
VOID *Resize
|
|
(
|
|
VOID *Address,
|
|
SBIT32 NewSize,
|
|
SBIT32 Move = 1,
|
|
SBIT32 *Space = NULL,
|
|
BOOLEAN NoDelete = False,
|
|
BOOLEAN Zero = False
|
|
);
|
|
|
|
BOOLEAN Truncate( SBIT32 MaxFreeSpace = 0 );
|
|
|
|
VOID UnlockAll( BOOLEAN Partial = False );
|
|
|
|
BOOLEAN Verify( VOID *Address,SBIT32 *Size = NULL );
|
|
|
|
BOOLEAN Walk
|
|
(
|
|
BOOLEAN *Active,
|
|
VOID **Address,
|
|
SBIT32 *Size
|
|
);
|
|
|
|
~HEAP( VOID );
|
|
|
|
//
|
|
// Public inline functions.
|
|
//
|
|
// Although these functions are public they mostly
|
|
// intended for internal consumption and are not
|
|
// to be called externally.
|
|
//
|
|
INLINE SBIT32 GetMaxFreePages( VOID )
|
|
{ return MaxFreePages; }
|
|
|
|
INLINE BOOLEAN KnownArea( VOID *Address )
|
|
{ return (Find -> KnownArea( Address,TopCache )); }
|
|
|
|
INLINE VOID *SpecialNew( SBIT32 Size )
|
|
{ return NewPage -> NewCacheStack( Size ); }
|
|
|
|
private:
|
|
//
|
|
// Private functions.
|
|
//
|
|
// All of the statistical information is
|
|
// generated and output when the heaps
|
|
// destructor executes.
|
|
//
|
|
CACHE *FindCache( SBIT32 Size );
|
|
#ifdef ENABLE_HEAP_STATISTICS
|
|
|
|
VOID PrintDebugStatistics( VOID );
|
|
#endif
|
|
//
|
|
// Private inline functions.
|
|
//
|
|
// The notion that resizing an allocation is
|
|
// cheap has worked its way into the minds of
|
|
// a large number of developers. As a result
|
|
// parameter has been added to the function to
|
|
// allow the actual behavior to be controlled.
|
|
//
|
|
INLINE BOOLEAN ResizeTest( SBIT32 Delta,SBIT32 Move )
|
|
{
|
|
return
|
|
(
|
|
((Move > 0) && ((((Delta >= 0) ? Delta : -Delta) >= Move)))
|
|
||
|
|
((Move < 0) && ((Delta > 0) || (Delta <= Move)))
|
|
);
|
|
}
|
|
|
|
//
|
|
// Disabled operations.
|
|
//
|
|
// All copy constructors and class assignment
|
|
// operations are disabled.
|
|
//
|
|
HEAP( CONST HEAP & Copy );
|
|
|
|
VOID operator=( CONST HEAP & Copy );
|
|
};
|
|
#endif
|